perl ssh to remote server, start service and capture pid - perl

title: perl ssh to remote server, start service and capture pid
1-please tell me if i am not clear, or i if am otherwise frustrating as i ask questions - i do not want to bite the hand that feeds me!
2-original file is 180 lines long, but here is the gist:
#!/usr/bin/perl -w
use strict;
use warnings;
use Net::SSH::Perl;
use Net::SSH::Expect;
use Time::HiRes qw(usleep nanosleep);
Time::HiRes::sleep(5); #5 seconds #a look at "top" verifies this running .pl file pid.
my $remoteCmd = `ssh $remote_host -l $userID -i /home/$userID/.ssh/authorized_keys /sbin/service /etc/init.d/c3-mi-nodeserver start`;
my $servicePID = $$; #this should be pid for .pl file running.
print "servicePID: " . $servicePID . "\n"; #prints the pid of the running .pl file.
of course, you'll see variables that i populate to make it work.
one idea i have is: if i start a service, it will be the pid # of the currently running .pl file + 1; but, the new service started is on a remote server, so how can i capture it from the remote server and return it back to the local .pl file?
ideas?

With that ssh command there's no way to capture the PID of the process you just started on a remote host.
You would need to use another ssh to find the process id. But really - what are you trying to accomplish by doing so? Can you not use service status and service stop to manipulate it?
If you really need a pid - service status might do it - or running a ps command.

Related

Run Perl Mojolicio Server from SSH

I have a mojolicio server on a machine where I connect to it from another machine. I have a script that checks if the mojolicio is up - and run it if it is not running. I use the following command line to run the server:
ssh root#hostname 'cd /server_path/; (nohup /usr/bin/perl server_file >nohup.out &);'
The server_file is a script that raise the server is has the following script:
#!/usr/bin/env perl
use Mojo::Base -strict;
use File::Basename 'dirname';
use File::Spec::Functions qw(catdir splitdir);
# Source directory has precedence
my #base = (splitdir(dirname(__FILE__)), '..');
my $lib = join('/', #base, 'lib');
-e catdir(#base, 't') ? unshift(#INC, $lib) : push(#INC, $lib);
# Start commands for application
require Mojolicious::Commands;
Mojolicious::Commands->start_app('MyServer', 'daemon','-l','http://*:3030');
If the server is down and I run this command - I see in the machine that the server is up and running and it listening to the port it configured to listen to. Now, if I try to connect to the server from the browser it don't not load. It stuck on loading and in the end I got page not found. But if I run the same command from the server itself it works and I can load the homepage after it runs.
I found the problem..
If I use the nohup with the ssh then the server somehow won't be reachable - but when I run the server without the nohup as for example - using the following code:
ssh root#hostname 'cd /server_path/; (usr/bin/perl server_file );'
it works.
what may be the problem here?
Thanks a lot.
I found the solution :-) - the problem was with the nohup command - it was missing the:
2>nohup.out
I added it and it works now.
Thanks everybody.

[Perl][net::ssh2] How to keep the ssh connection while executing remote command

I'm working on a perl script using net::ssh2 to make a SSH connection to a remote server.
(I'm working on windows)
I chose Net::SSH2 because i had to make some SFTP connections in the same script.
For now, my sftp connections work perfectly. The problem is when i try to execute a "long-duration" command. I mean a command which execution can take more than 30sec.
$ssh2 = Net::SSH2->new();
$ssh2->connect('HOST') or die;
if($ssh2->auth(username=>'USER', password=>'PSWD'))
{
$sftp = Net::SFTP::Foreign->new(ssh2=>$ssh2, backend=>'Net_SSH2');
$sftp->put('local_path', 'remote_path');
$channel=$ssh2->channel();
##
$channel->shell('BCP_COMMAND_OR_OTHER_PERL_SCRIPT');
# OR (I tried both, both failed :( )
$channel->exec('BCP_COMMAND_OR_OTHER_PERL_SCRIPT');
##
$channel->wait_closed();
$channel->close();
print "End of command";
$sftp_disconnect();
}
$ssh2->disconnect();
When i execute this script, the connection is successfull, the file is correctly sent but the execution is not (completely) performed. I mean, I think the command is sent for execution but terminated immediatly or not sent at all, i'm not sure.
What i want is the script waits until the command is completly finished before disconnect everything (just because sometimes, i need to get the result of the command execution)
Does anyone know how to solve this? :( The cpan documentation is not very explicit for this
Thanks!
PS: I'm open to any remarks or suggestion :)
Edit: After some test, i can say that the command is sent but is interrupted. My test was to start another perl script on the remote server. This script writes in a flat file. In this test, the script is started, the file is half-filled. I mean, the file is brutaly stopped in the middle.
In the other hand, when i performed a "sleep(10)" just after the "$channel->exec()", the script goes to the end successfully.
Problem is, that I can't write a "sleep(10)" (i don't know if it will take 9 or 11 seconds (or more, you see my point)
You can try using Net::SSH::Any instead.
It provides a higher level and easier to use API and can use Net::SSH2 or Net::OpenSSH to handle the SSH connection.
For instance:
use Net::SSH::Any;
my $ssh = Net::SSH::Any->new($host, user => $user, password => $password);
$ssh->error and die $ssh->error;
my $sftp = $ssh->sftp;
$sftp->put('local_path', 'remote_path');
my $output = $ssh->capture($cmd);
print "command $cmd output:\n$output\n\n";
$sftp->put('local_path1', 'remote_path1');
# no need to explicitly disconnect, connections will be closed when
# both $sftp and $ssh go out of scope.
Note that SFTP support (via Net::SFTP::Foreign) has been added on version 0.03 that I have just uploaded to CPAN.

How can I get STDERR and STDOUT of a command executed on a remote machine through SSH in Perl?

I have to connect to a remote machine via SSH executed through Expect module. I have to access the STDERR/STDOUT separately if possible and look at the output. I can redirect the output of the script e.g.
$command = "ssh <script> 2>/tmp/stderr.output"
$exp = Expect->spawn($command) or die "Cannot spawn\n";;
my #command1= $exp->expect(5);
but then I have to remotely connect again to check stderr.output.
Is there a way that expect returns the STDERR/STDOUT separately.
You might want to consider using Net::OpenSSH which provides a capture2 method:
($output, $errput) = $ssh->capture2(\%opts, #cmd)
captures the output sent to both stdout and stderr by #cmd on the remote machine.

Insert rsh and module load in perl script

I am writing a perl script to start vnc session.
Firsr I need to rsh to a server then load a module, next execute the "vncserver -otp".
my $mod=`module load turbovnc-1.0.0; vncserver -otp 2> tmp_vnc.log`;
my $launch=`rsh $host /"$mod/"`;
print $launch;
But it does not work, any suggestions??
Thanks!!
Did you mean to use backticks in your first line?
my $mod=`module load turbovnc-1.0.0; vncserver -otp 2> tmp_vnc.log`;
This sets $mod to be the output of this sequence of commands, like running
(module load turbovnc-1.0.0; vncserver -otp 2> tmp_vnc.log) | rsh $host
from the shell. You probably wanted to say
my $mod='module load turbovnc-1.0.0; vncserver -otp 2> tmp_vnc.log';
which will set you up to run those specific commands on the remote host, and execute
rsh $host "module load turbovnc-1.0.0; vncserver -otp 2> tmp_vnc.log"
It also looks like in the rsh command that you are trying to escape the quotation marks with forward slashes. In Perl (and in everything else as far as I know), use a backslash to escape a special character.
my $launch=`rsh $host /"$mod/"`; # / wrong /
my $launch=`rsh $host \"$mod\"`; # \ right \
my $launch=`rsh $host "$mod"`; # right, esc is not reqd in this case
A number of things could be going wrong, but probably the system commands are quietly failing. Either loading the module, starting the vncserver or the rsh. You can manually check for their success or failure by checking $? after each command... or you can use IPC::System::Simple and it will error out if the command fails.
I would start by doing it as a series of shell commands to make sure it works.
Then I'd rewrite the code like so using IPC::System::Simple to do the error checking. Also separating the $mod command into two commands, because I suspect you're getting back the output of running the vncserver, not loading the module.
use strict;
use warnings;
use IPC::System::Simple qw(run capture);
my $host = "something.something";
# Capture the output of loading the module
my $mod = capture('module', 'load', 'turbovnc-1.0.0');
warn "Module output: $mod\n";
# Run the VNC server
run('vncserver -otp 2> tmp_vnc.log');
# Connect to the host
my $launch = capture('ssh', $host, "/$mod/");
warn "ssh output: $launch";
There would seem to be a possibly false assumption that the location of the module on this machine is the same as the location of the module on the remote machine. That or I don't understand what you're doing with $mod.

problem making an SSH session using perl

use Net::SSH::Perl;
my $ssh = Net::SSH::Perl->new('$host',22);
$ssh->login('$user','$pass');
my $out = $ssh->cmd("show clock");
print $out;
I have the above script to have an ssh session using perl but I'm having the error message
"Can't map service name 'ssh' to port number". I'm using Windows OS. Please advise me where I'm wrong.
Try adding ssh to your services file. The services file is located at:
%SystemRoot%\system32\drivers\etc\services
The line that you'll want to add will look like:
ssh 22/tcp # Secure Shell Login