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.
Related
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.
I am trying to run a couple of commands in putty from perl. Right now my code gets me into putty but I am unsure of how to execute commands from there.
my $PUTTY = 'C:\Users\Desktop\putty.exe';
my $dacPutty = "$PUTTY, -ssh username#server - l username -pw password";
system ($dacPutty);
system (ls);
use plink instead. ( http://the.earth.li/~sgtatham/putty/0.60/htmldoc/Chapter7.html )
plink is in the same directory as putty.
Usually in Perl it's better to use a Perl module, where one exists, than to shell out.
Using a module is more portable, and often gives you more control. system introduces many opportunities for security bugs, so it's good to avoid it where possible.
In this case, use Net::SSH::Perl http://search.cpan.org/~turnstep/Net-SSH-Perl-1.38/lib/Net/SSH/Perl.pm
Once installed:
use Net::SSH::Perl;
my $ssh = Net::SSH::Perl->new("host1");
$ssh->login("user1", "pass1");
$ssh->cmd("cd /some/dir");
$ssh->cmd("foo");
For reliability, you should actually check the result of each cmd:
my ($stdout, $stderr, $exit) = $ssh->cmd("cd /some/dir");
unless ($exit == 0) {
// Handle failed cd
}
The document notes that with SSH-1, each cmd reconnects, so the above would not work -- you would cd in one shell, then foo in a completely new shell. If you have to use SSH-1, then you'd need to do:
$ssh->cmd("cd /some/dir; foo");
(And you can use a similar trick even if you're making a system call to plink)
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.
I am bit stuck here I want to ssh in to a machine and then run about 3 commands which are basically setup commands and then i want to return back to my machine with env variables of that machine
like
setup1
setup2
setup3
env > envtext.txt.
return back
All this i have to do in perl
i tried commands like
system("ssh #machine command1 && command 2") doesnt work
is there something like?
system("ssh #machine command1 -cmd command 2 -cmd command 3")
if not than what is the best way to do it
like making a shell script then calling it or i can do it in perl itself without any shell scripts?
code
#!/usr/bin/perl -w
use Net::SSH::Perl;
my $host = "address";
my $user = "name";
my $password = "password";
-- set up a new connection
my $ssh = Net::SSH::Perl->new($host,
debug=>0,
identity_files => ['path to key'],
options=> ["StrictHostKeyChecking no"]
#interactive => yes,
);
-- authenticate
$ssh->login($user,$password);
-- execute the command
my($stdout, $stderr, $exit) = $ssh->cmd("env");
print $stdout;`
error it gives is Permission denied at ssh.pl line 25
Thank you
I think your question is about SSHing to a single remote host and running multiple commands there. If that's true, then you need to pack your multiple commands up into a single command line that the remote shell can execute. The easiest way to do this is to use the list form of system, and pass the command line as a single parameter:
system "ssh", "machine", "setup1; setup2; setup3";
On to the second part of your question: You want to get data back from the remote side. For that, you'll want your program to read SSH's output rather than using system. For this, you can use:
open my $FH, "-|", "ssh", "machine", "setup1; setup2; setup3; env";
my #lines_from_ssh = <$FH>;
close $FH;
If you also need to send input to the remote side, look into IPC::Open2. If you need to capture both stdout and stderr, see IPC::Open3.
What you can do :
system("ssh $_ command1 -cmd command 2 -cmd command 3") for #machines;
Another Pure Perl solution is to use Net::OpenSSH
I need to write a CGI program and it will display the output of a system command:
script.sh
echo "++++++"
VAR=$(expect -c " spawn ssh -o StrictHostKeyChecking=no $USER#$HOST $CMD match_max
100000 expect \"*?assword:*\" send -- \"$PASS\r\" send -- \"\r\" expect eof ")
echo $VAR
echo "++++++"
In CGI file:
my $command= "ksh ../cgi-bin/script.sh";
my #output= `$command`;
print #output;
Finally, when I run the CGI file in unix, the $VAR is a very long string including \n and some delimiters. However, when I run on web server, the output is
++++++
++++++
So $VAR is missing when passing in the web interface/browser.
I know maybe the problem is $VAR is very long string.
But anyway, is there anyway to solve this problem except writing the output to a file then retrieve it from browser?
Thanks if you are interested in my question.
script.sh uses several environment variables: $USER, $HOST, $CMD and $PASS. The CGI environment will have different environment variables set than a login shell. You may need to set these variables from your CGI script before calling script.sh.
Try finding where commands like expect and ssh that you are calling are on your system and adding their directory paths to the PATH used by your script.
I.e.
which expect
returns /usr/bin/expect then add the line:
PATH=$PATH:/usr/bin && export PATH
near the beginning of the ksh script. During debug you may also want to redirect stderr to a file by appending 2>/tmp/errors.txt to the end of your command since stderr is not shown in the browser.
my $command= "ksh ../cgi-bin/script.sh 2>/tmp/errors.txt";