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

Greetings,
I find myself in a bit of a bind. I'm looking for a module or perhaps method that will allow me to connect via a bastion host to a remote machine (ssh). at this point i need to execute commands and store the values in either a scalar with \n to parse into an array or directly into an array.

I've looked inot using the expect module, but from what i can tell ->before only pulls a single line. Maybe i'm missing something.

I've also attempted to use Net::Tel , using a ssh session spawned to a PTY, then interacting with the PTY. The problem with this is that with at least all the versions of openssh i use it requires a valid tty or i can't auth.

That brings up the idea of using passwordless dsa keys, but i'm not fond of this.

Now i can execute an actual expect script for each command and pull the return values into an array, but that means i need to establish an individual connection for each command. And that's jut plain wasteful.

So, the question i pose is ... what other options do i have?

Replies are listed 'Best First'.
Re: interact with remote host via bastion
by tachyon (Chancellor) on Feb 15, 2003 at 11:02 UTC

    You want Net::SSH or Net::SSH::Perl which is pure Perl and does not shell out to ssh(1)

    use Net::SSH qw(sshopen2); use strict; my $user = "username"; my $host = "hostname"; my @cmds = ( "command1", "command2", "etc" ); my %results; for my $cmd ( @cmds ) { sshopen2("$user\@$host", *READER, *WRITER, "$cmd") || die "ssh: $! +"; my $result = ''; $result .= $_ while <READER>; $results{$cmd} = $result; } close READER; close WRITER;

    This will build a hash $results with the key:value pairs of the command and its result. Note you will lose results if you exec exactly the same command twice as hash keys are unique. If you just want an array of the results do:

    my @results; for my $cmd ( @cmds ) { sshopen2("$user\@$host", *READER, *WRITER, "$cmd") || die "ssh: $! +"; my $result = ''; $result .= $_ while <READER>; push @results, $result; }

    Note if you don't want to use DSA or RSA and wish to supply a login password use Net::SSH::Perl

    cheers

    tachyon

    s&&rsenoyhcatreve&&&s&n.+t&"$'$`$\"$\&"&ee&&y&srve&&d&&print

      I looked into this, and while it would work fairly well via one host, the bastion in the middle causes some problems.

      perhaps i should have explained that more clearly earlier.

      localhost ->ssh to bastion ->ssh to remotehost->command

      i'd like to keep the chain alive.

      Thanks for your help, but it looks like i'm going to have to rewrite the pty code in order to pull this off.

        Just write a passthrough script for the bastion. All you have to do is SSH into the bastion and fire up the passthrough script. Pass commands to this script which then passes them on to another host and printing the resulting output to STDOUT which by default will go back to you localhost. Such a script might look like this:

        #!/usr/bin/perl # passthrough SSH script use Net::SSH qw(sshopen2); use strict; my $user = "username"; my $host = "hostname"; while ( my $cmd = <> ) { last if $cmd =~ /exit_passthrough/; sshopen2("$user\@$host", *READER, *WRITER, "$cmd") || print "ssh: +$!"; my $result = ''; $result .= $_ while <READER>; print $result; } close READER; close WRITER;

        Effectively this creates a basic SSH secured shell in the middle for you. A bonus is that you can get the script to work on the bastion box and then step back to localhost to make debugging straight forward.

        cheers

        tachyon

        s&&rsenoyhcatreve&&&s&n.+t&"$'$`$\"$\&"&ee&&y&srve&&d&&print