linuxfan has asked for the wisdom of the Perl Monks concerning the following question:

Holy Monks,

I am using the Net::SSH::Perl module to run commands on a remote linux server (located in the same LAN). It appears to me that I am having a timing problem. The relevant part of my code looks like this:

my $cmd = Generate_Command($arg1,$arg2); $ssh->cmd($cmd); $cmd = Generate_Another_Command($arg1,$arg2); $ssh->cmd($cmd);
The execution time of the command on the remote server varies with what arguments are passed. For e.g, if DES encryption is required, it takes about 1 min and if RSA is used it takes 10 mins.

The problem I am facing is that perl seems to execute the next line of code without the first command over ssh running to completion. As a result, the second command over ssh fails (as it depends on the first). Is there a workaround for this problem? I tried implementing a solution with fork() where the SSH stuff runs in the child and the parent waits for it to complete, but this hasn't worked for me either. Can someone suggest an efficient method to wait for the command on the remote to server to return before moving on to the next line of code?

The command I run on the server is a shell script executes a few java classes. It looks something like this:

#! export CLASSPATH=/usr/local/classes/classes12.zip PATH=/usr/local/java/bin:$PATH export LD_LIBRARY_PATH=/usr/local/tonga/lib /usr/local/tonga/bin/javadb dbVersion $1
Thanks a lot,
linuxfan Update: All monks,

Thanks for your suggestions. I am working on the script now and will post any updates as soon as I find them.

Replies are listed 'Best First'.
Re: How to hold execution of perl script while it runs command on remote machine
by fizbin (Chaplain) on Feb 19, 2005 at 02:40 UTC
    If perl is moving on to other statements, then the command has finished on the remote server, or you've found a nasty bug inside Net::SSH:Perl. I suspect that something else is going wrong here, so here's how I'd debug it.

    First off, inside your perl script add some statements showing the result of the command; a quick-and-dirty way would be:

    use Data::Dumper; my $cmd = Generate_Command($arg1,$arg2); print Dumper([$ssh->cmd($cmd)]); $cmd = Generate_Another_Command($arg1,$arg2); print Dumper([$ssh->cmd($cmd)]);
    Then, assuming that alone doesn't produce any useful diagnostic information, try modifying your shell script on the remote server to be a bit noisier:
    #! /bin/sh set -x CLASSPATH=/usr/local/classes/classes12.zip PATH=/usr/local/java/bin:$PATH LD_LIBRARY_PATH=/usr/local/tonga/lib export CLASSPATH export PATH export LD_LIBRARY_PATH echo "About to start java at `date`" /usr/local/tonga/bin/javadb dbVersion $1 javastat=$? echo "Finished java at `date` with status $javastat" exit $javastat
    I strongly suspect that the combination of these two changes will show that something else is going on, if the answer isn't apparent as soon as you make the first perl change above.
    -- @/=map{[/./g]}qw/.h_nJ Xapou cets krht ele_ r_ra/; map{y/X_/\n /;print}map{pop@$_}@/for@/
      As weird as this may sound, I ran my script against a different server (where all the commands run), and have not faced any problems since then. Thanks much for your suggestions!
Re: How to hold execution of perl script while it runs command on remote machine
by perlfan (Parson) on Feb 19, 2005 at 03:43 UTC
    Just as a test, how long does it take to run these commands with ssh? It may even be a dns lookup issue.
      The client and server are both on the same LAN. Moreover, I use IP addresses in the script, so DNS is not an issue.

      Thanks!

Re: How to hold execution of perl script while it runs command on remote machine
by Anonymous Monk on Feb 19, 2005 at 18:33 UTC
    is it possible to combine the set of commands into one so that you only need to do ssh once and run this one command ?

    BTW, Comparing to the openssh (and others?), Net::SSH::Perl is much slower when trying to establish the connection. you can setup your ssh key on both side to speed it up.

      # ssh user@host 'command1 && command2 && command3...'
      Also note that using single quotes allows you to save wildcard expansion for the remotehost side.
      oops, forgot to login.
      I create only one SSH connection at the beginning of my script, and use this handle to send commands to the server. The overhead of using Net::SSH::Perl over openssh with public key authentication does not seem to hurt my program's performance.

      Thanks!