简体   繁体   English

如何在 Perl 脚本中使用 ssh?

[英]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.我想通过 SSH 连接到服务器并执行一个像“id”这样的简单命令并获取它的输出并将其存储到我的主服务器上的一个文件中。 I do not have privileges to install Net::SSH which would make my task very easy.我没有安装Net::SSH 的权限,这将使我的任务变得非常简单。 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.我尝试使用反引号,但无法将输出存储在运行脚本的机器上。

The best way to run commands remotely using SSH is使用 SSH 远程运行命令的最佳方法是

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

You can use this either in bash or in perl.您可以在 bash 或 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? ".但是,如果您想使用 perl,您可以按照 brian 在他的评论中或“ 如何保留我自己的模块/库目录? ”中的 Perl 常见问题解答中的建议,将 perl 模块安装在您的本地目录路径中。 Instead of using Net::SSH I would suggest to use Net::SSH::Perl with the below example.我建议在下面的示例中使用 Net::SSH::Perl,而不是使用 Net::SSH。

#!/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;

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"

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;

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.我使用qx()并像往常一样运行 ssh 命令。 The catch is I had to capture both stderr and stdout.问题是我必须同时捕获 stderr 和 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 .它运行python -V命令,该命令将版本信息输出到stderr In this example, my ip address was stored in the $curIP variable.在这个例子中,我的 IP 地址存储在$curIP变量中。 Lastly, the 2>&1 helps capture both stdout and stderr.最后, 2>&1有助于捕获标准输出和标准错误。 I did not specify a password, as I have key exchanges setup.我没有指定密码,因为我设置了密钥交换。 Hope this helps.希望这可以帮助。

If you're using backticks try this:如果您使用反引号,请尝试以下操作:

my @output = `ssh root@1.1.1.1 "which perl"`;

print "output: @output";

This is only useful if you have a publickey that the above command won't prompt for password.这仅在您拥有上述命令不会提示输入密码的公钥时才有用。

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
    }
}

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.如果您设置了 ssh 主机密钥,您可以简单地运行 ssh 系统命令,然后指定要在机器上运行的命令。 For example:例如:

`ssh user@remoteserver.domain.com id`

You should be able to chomp/store that output.您应该能够 chomp/store 该输出。

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如果您可以设置 ssh 密钥,那么只需使用已经发布的反引号命令,尽管您可能需要 -i 选项

#!/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();

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.我知道这是一个非常古老的线程,但由于我遇到了同样的问题,我找到了另一个有用的解决方案,以防有人使用 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.这假设您已配置 ssh-keys,因此不需要用户输入。 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.我正在使用readpipe来实现这一点。

Hope this helps to have a solution in case of not hard coding.希望这有助于在非硬编码的情况下提供解决方案。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM