Salman
Salman

Reputation: 121

How can I ssh inside a Perl script?

I want to SSH to a server and execute a simple command like "id" and get the output of it and store it to a file on my primary server. I do not have privileges to install Net::SSH which would make my task very easy. Please provide me a solution for this. I tried using back-ticks but I am not able to store the output on the machine from which my script runs.

Upvotes: 12

Views: 109869

Answers (9)

bicepjai
bicepjai

Reputation: 1665

use warnings;
use strict;
use Net::SSH2;

sub is_sshalive;

my $host = "ip"; # use the ip host to connect
my $user = "UNAME"; # your account
my $pass = "PASSWD"; # your password
my $cmd;
my $ssh2 = Net::SSH2->new();
$ssh2->debug(1);
if ($ssh2->connect($host)) {
    #if ($ssh2->auth_password($user,$pass)) {
    if ($ssh2->auth_keyboard($user,$pass)) {
        print "\n Executing command...\n";
        $cmd = "ls";
        print " ==> Running $cmd\n";
        if(is_sshalive($ssh2) == 1) {
                print "\nSSH connection died";
                exit 1;
        } else {
            run_testsuite($cmd, $ssh2);
        }
    } else {
        warn "ssh auth failed.\n";
        exit 1;
    }
} else {
    warn "Unable to connect Host $host \n";
    exit 1;
}
print "test passed done 0\n";


sub run_testsuite {
    my $cmd = $_[0];
    my $ssh2 = $_[1];

    my $chan2 = $ssh2->channel();
    $chan2->shell();
    print $chan2 "$cmd \n";
    print "LINE : $_" while <$chan2>;
    $chan2->close;
    return 0;
}

sub is_sshalive {
    my $ssh2 = $_[0];
    if ($ssh2->poll(1000) == 0) {
        return 0; # passed
    } else {
        return 1; #failed
    }
}

Upvotes: 0

Space
Space

Reputation: 7259

The best way to run commands remotely using SSH is

$ ssh user@host "command" > output.file

You can use this either in bash or in perl. However, If you want to use perl you can install the perl modules in your local directory path as suggested by brian in his comment or from Perl FAQ at "How do I keep my own module/library directory?". Instead of using Net::SSH I would suggest to use Net::SSH::Perl with the below example.

#!/usr/bin/perl -w
use strict;
use lib qw("/path/to/module/");

use Net::SSH::Perl;

my $hostname = "hostname";
my $username = "username";
my $password = "password";

my $cmd = shift;

my $ssh = Net::SSH::Perl->new("$hostname", debug=>0);
$ssh->login("$username","$password");
my ($stdout,$stderr,$exit) = $ssh->cmd("$cmd");
print $stdout;

Upvotes: 16

Thanos
Thanos

Reputation: 1778

I know this is a very old thread, but since I encounter the same problem I found another useful solution in case that someone is using Linux.

#!/usr/bin/perl
use strict;
use warnings;
use Data::Dumper;

my $host = $ARGV[0];
my $port = $ARGV[1];
my $cmd = $ARGV[2];

my @output = readpipe( "ssh -p ".
               $port." ".
               $host." ".
               $cmd."" );

chomp @output;

print Dumper \@output;

__END__

perl sample.pl 127.0.0.1 22 "which perl"
Ubuntu 16.04.1 LTS
$VAR1 = [
          '/usr/bin/perl'
        ];

This assumes that you have configured ssh-keys so no user input will be required. I did not want to have hard coded values this is the best way for me that worked the best. I am using readpipe to achieve that.

Hope this helps to have a solution in case of not hard coding.

Upvotes: 0

James Oravec
James Oravec

Reputation: 20391

I had a similar issue, and after much searching I've found a simple option. I used qx() and ran the ssh commands like I normally would. The catch is I had to capture both stderr and stdout.

The following is an example of what I used:

my $output = qx(ssh root\@$curIP python -V 2>&1);

It runs the python -V command, which outputs the version info to stderr. In this example, my ip address was stored in the $curIP variable. Lastly, the 2>&1 helps capture both stdout and stderr. I did not specify a password, as I have key exchanges setup. Hope this helps.

Upvotes: 1

James
James

Reputation: 21

or, assuming host keys are present and you want to do something with the command ouput ...

open(SSH,"/usr/bin/ssh you\@server ps aux |") or die "$!\n";
while (<SSH>) { 
   # do stuff with $_ 
}
close SSH;

Upvotes: 2

Ricky Levi
Ricky Levi

Reputation: 7987

If you're using backticks try this:

my @output = `ssh [email protected] "which perl"`;

print "output: @output";

This is only useful if you have a publickey that the above command won't prompt for password.

Upvotes: 1

John Mikkola
John Mikkola

Reputation: 47

Assuming that you're in an environment like me where you can't add additional modules and you can't create an Identity file, then you can use this script as a starting point.

If you can set up ssh keys then simply use the backticks command already posted, although you might need the -i option

#!/usr/bin/perl
use warnings;
use strict;
use Expect;
use Data::Dumper;

my $user = 'user';
my $pw = 'password';
my $host = 'host';
my $cmd = 'id';

my $exp = new Expect;
$exp->log_file("SSHLOGFILE.txt");
$exp->log_stdout(0);
$exp->raw_pty(1);


my $cli = "/usr/bin/ssh $user\@$host -o StrictHostKeyChecking=no -q $cmd";

$exp->spawn($cli) or die "Cannot spawn $cli: $!\n";

$exp->expect(5,
 [ qr /ssword:*/ => sub { my $exph = shift;
                          $exph->send("$pw\n");
                          exp_continue; }] );

my $read = $exp->exp_before();
chomp $read;
print Dumper($read);

$exp->soft_close();

Upvotes: 0

Chas. Owens
Chas. Owens

Reputation: 64909

You can always install modules locally, and that is the method you should look into; however, you should be able to get away with

#!/usr/bin/perl

use strict;
use warnings;

my $id = qx/ssh remotehost id 2>&1/;

chomp $id;

print "id is [$id]\n"

Upvotes: 8

malonso
malonso

Reputation: 2295

If you have ssh host keys setup you can simply run the ssh system command and then specify the command to run on the machine after that. For example:

`ssh [email protected] id`

You should be able to chomp/store that output.

Upvotes: 1

Related Questions