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

Monks,

Could someone please enlighten me on the difference between using Net::ssh and Net::ssh::perl. On my machine, I can write a small piece of code using, net::ssh. But using the examples found on the web I can't use net::ssh::perl, that gives an error.

Also, I need to be able to execute multiple commands once I am logged in. Can someone show me the syntax for issuing multiple commands with net::ssh? here's the syntax I am using from the examples I was given:

#!/usr/bin/perl use Net::SSH qw(sshopen2); use strict; my $user = "cosmicsoup"; my $host = "mybox.somewhere.com"; my $cmd = "df -k /data/staging"; sshopen2("$user\@$host", *READER, *WRITER, "$cmd") || die "ssh: $!"; while (<READER>) { chomp(); print "$_\n"; } close(READER); close(WRITER);
Many thanks,

Louis

Replies are listed 'Best First'.
Re: Net::ssh vs Net::ssh::perl
by jasonk (Parson) on Feb 19, 2003 at 19:08 UTC

    The difference between the two is that Net::SSH is a wrapper, you have to have ssh installed on the machine where you are using, while Net::SSH::perl is a perl implementation of the entire protocol, so you don't need the ssh program installed on the machine.

    The easiest way to issue multiple commands with the code you have is to change $cmd to be a shell (such as '/bin/sh'), and then use WRITER to write a command to the shell, and read the results from READER. You will need a way to determine when the command is finished though, so you can break out of the READER loop..

    Untested code, I prefer Net::SSH::perl...

    #!/usr/bin/perl use Net::SSH qw(sshopen2); use strict; my $user = "cosmicsoup"; my $host = "mybox.somewhere.com"; my $cmd = "/bin/sh"; my @commands = ('df -k','free','uptime'); sshopen2("$user\@$host", *READER, *WRITER, "$cmd") || die "ssh: $!"; foreach(@commands) { print WRITER "$_ && echo DDDOOONNNEEE\n"; while (<READER>) { chomp(); last if /DDDOOONNNEEE/; print "$_\n"; } } close(READER); close(WRITER);

    Since you are using the version that uses the external ssh command anyway, you could also look at using something like Expect, and just run ssh yourself.

      Thank you. That makes complete sense. I'll contact the SA's to see if I can have the Net::ssh::perl and expect installed on my machine.

      Louis

        and here's a little example of Expect and plain old ssh.

        #!/usr/bin/perl use strict; use warnings; $|++; use Expect; # a heading for the run my $section = shift @ARGV; my $want_stdout = 0; unless ( defined $section and length $section ) { $section = 'intentionally left blank'; $want_stdout = 1; } my $router = 'rtr_foo'; my $timeout = 20; my $tmp_log = "/tmp/ssbinfo.$$"; my $real_log = "/home/network/SSB-INFO.LOG"; my $su_pass = 'yeahright'; my $ssh_user = 'automatron'; my $ssh_id = '/home/network/bin/automatron.identity'; my $ssh = '/usr/bin/ssh'; my $ssh_spawn = "$ssh -l $ssh_user -i $ssh_id -x $router"; eval { # catch failures!!! my $e = Expect->new() or die "No new Expect!\n"; $e->log_stdout(0); # no logging yet #$e->debug(2); #$e->exp_internal(1); # debug more # $e->raw_pty(1); # didn't seem to need these #$e->stty(qw/raw -echo/); #$e->slave->stty(qw/raw -echo/); $e->spawn( $ssh_spawn ) or die "Cannot spawn ssh with: $ssh_spawn : be +cause $!\n "; my $ssb_prompt = "SSB0\\(${router} vty\\)# "; my $root_prompt = "root\@${router}% "; my $shell_prompt = '% '; my $rtr_prompt = "${ssh_user}\@${router}> "; $e->expect( $timeout, [ qr/^$rtr_prompt/ => sub { my $e = shift; $e->send("start shell\n"); exp_continue; } ], [ qr/^$shell_prompt/ => sub { my $e = shift; $e->send("su\n"); exp_continue; } ], [ qr/^Password:/ => sub { my $e = shift; $e->send("$su_pass\n"); exp_continue; } ], [ qr/^$root_prompt/ => sub { my $e = shift; $e->log_file($tmp_log, 'w'); # w for overwrite, just +in case $e->send("date\n"); $e->expect($timeout, [ qr/^$root_prompt/ => sub { my $e = shift; $e->send("vty ssb\n"); } ], ); exp_continue; } ], [ qr/^$ssb_prompt/ => sub { my $e = shift; $e->send("set syslog tty disable\n"); $e->expect($timeout, [ qr/^$ssb_prompt/ => sub { } ],) +; } ], [ 'Cannot exec' => sub { die "Cannot exec ssh with: $ssh_spawn!\n"; } ], ) or die "failed getting to the ssb!\n"; # eww! cut-n-paste evil $e->send("show heap 0\n"); $e->expect($timeout, [ qr/^---\(more\)---/ => sub { my $e = shift; $e->send("\n"); exp_continue; } ], [ qr/^$ssb_prompt/ => sub { } ], ) or die "failed command 1!\n"; $e->send("show heap 0 accounting pc\n"); $e->expect($timeout, [ qr/^---\(more\)---/ => sub { my $e = shift; $e->send("\n"); exp_continue; } ], [ qr/^$ssb_prompt/ => sub { } ], ) or die "failed command 2!\n"; $e->send("show heap 0 accounting size\n"); $e->expect($timeout, [ qr/^---\(more\)---/ => sub { my $e = shift; $e->send("\n"); exp_continue; } ], [ qr/^$ssb_prompt/ => sub { } ], ) or die "failed command 3!\n"; # # turn off logging # $e->log_file(undef); $e->send("exit\n"); $e->expect($timeout, [ qr/^$root_prompt/ => sub { } ]) or die "failed exit ssb!\n"; $e->send("exit\n"); $e->expect($timeout, [ qr/^$shell_prompt/ => sub { } ]) or die "failed exit su!\n"; $e->send("exit\n"); $e->expect($timeout, [ qr/^$rtr_prompt/ => sub { } ]) or die "failed exit shell!\n"; $e->send("exit\n"); sleep 1; 1 or die "can't screw up exit router!\n"; $e->soft_close(); $e = undef; # clean up temporary file use Fcntl qw(:flock); open(IN, '<', $tmp_log) or die "Can't find $tmp_log\n"; if ( $want_stdout ) { *NI = *STDOUT; } else { open(NI, '>>',$real_log)or die "Can't find $real_log\n"; flock(NI, LOCK_EX); } print NI $/; if ( defined $section and length $section ) { print NI "#$/# Begin: ${section}$/#$/"; } while (<IN>) { next if $. == 1 and /^date/; # just looked ugly # next two lines fix up a few syslog messages # that make it through before we could turn # them off next if /^\[/; print(NI "SSB0(rtr_foo vty)# "),next if /^SSB0\(rtr_foo vty\)# + \[/; s/---\(more\)---\r//; # damn pager s/\r//; print NI $_; } print NI $/; if ( defined $section and length $section ) { print NI "#$/# End: ${section}$/#$/"; } close(NI) if !$want_stdout; # unlocks if locked, don't close STDOUT! close(IN); }; # end great big eval if ($@) { print "$@"; } unlink $tmp_log; exit;

        which was hastily written (probably self evident) to do a couple of logins and run some commands.

        $ ssh -l automatron -i /home/network/bin/automatron.identity -x rtr_foo
        ...
        automatron@rtr_foo> start shell
        ...
        % su
        Password: ****
        ...
        root@rtr_foo% date
        ...
        root@rtr_foo% vty ssb
        .....
        SSB0(rtr_foo vty)# set syslog tty disable
        ...
        SSB0(rtr_foo vty)# show heap 0
        ...
        ---(more)---
        ...
        SSB0(rtr_foo vty)# show heap 0 accounting pc
        ...
        ---(more)---
        ...
        SSB0(rtr_foo vty)# show heap 0 accounting size
        ...
        ---(more)---
        ...
        SSB0(rtr_foo vty)# exit
        ...
        root@rtr_foo% exit
        ...
        % exit
        ...
        automatron@rtr_foo> exit
        
(jeffa) Re: Net::ssh vs Net::ssh::perl
by jeffa (Bishop) on Feb 19, 2003 at 19:12 UTC
    I would guess that you received errors when you tried Net::SSH::Perl because it is not installed on your computer. See A Guide to Installing Modules for more on that.

    Personally, i would use Net::SSH::Perl, because i have found it to be easier to use. I am not sure if Net::SSH offers a way to abstract having to read from the child process or not, but Net::SSH::Perl definitely does. I would give an example, but i have already posted one today over at Creating path on remote host. Best of luck. :)

    jeffa

    L-LL-L--L-LL-L--L-LL-L--
    -R--R-RR-R--R-RR-R--R-RR
    B--B--B--B--B--B--B--B--
    H---H---H---H---H---H---
    (the triplet paradiddle with high-hat)