perl远程执行错误

时间:2012-03-21 06:41:03

标签: linux perl ssh perl-module

在下面的代码中,我尝试使用Perl脚本将git存储库克隆到另一台机器。

如果我打印$output,我会收到所有登录消息,即/etc/motd/的内容,但不是实际的命令输出。

如何解决此问题?我在执行ssh命令时做错了吗?

    sub myexec_remote    
    {
       my($cmd, $hostname, $filename) = @_;

       my $stdout = $stderr = $exit= "";
       my ($output) = `ssh $hostname $cmd 2>&1`;
       ## this is the command i.e, executed
       ##command is  ssh 111.22.11.32 "git clone --bare gt@l.com:/nfs/git/ /nfs/new123/"
       $exit = $?;
       if (defined $output)
       {
       open(MYOUTFILE, ">$filename");
       print MYOUTFILE "$output";
       close(MYOUTFILE);
       }

    }

我正在使用反引号,因为有时ssh已经完成而没有无密码我已经看到NET:SSH模块不支持它...

2 个答案:

答案 0 :(得分:2)

这是因为您在列表上下文中使用backticks operator

my ($output) = `ssh $hostname $cmd 2>&1`;

在列表上下文中调用时,反引号将返回一个行列表。您只捕获第一行,并将其放在$output中。其他行被忽略。来自perldoc perlop

  

在标量上下文中,它作为单个(可能是多行)返回   字符串,如果命令失败,则为undef。在列表上下文中,返回a   行列表(但是你用$ /或定义了行   $ INPUT_RECORD_SEPARATOR),如果命令失败,则为空列表。

解决方案:

1. my $output = `ssh $hostname $cmd 2>&1`;

在标量上下文中调用反引号将导致$ output为多行字符串。

2. my @output = `ssh $hostname $cmd 2>&1`;

您可以在数组上下文中调用反引号,但是您必须稍后将整个数组打印到MYOUTPUTFILE

其他评论:

这些不是解决方案的一部分。解决方案本身应足以修复您的错误。但是,它们可以降低错误风险,并提高您的Perl知识。

  1. 尝试使用open的三参数版本,而不是使用全局的两参数,并在无法打开文件时捕获错误:

    open(my $handle, '>', $filename) or die "Unable to open file, $!";

  2. 很多人决定使用IPC::System::Simple而不是反引号,因为当出现问题时您可以获得更多信息并且可以避免使用shell。

  3. 另一个选项是IPC::Open3,它甚至可以让您轻松捕获STDOUT,STDERR和exitcode。但是使用起来有点困难。

答案 1 :(得分:0)

使用Net::OpenSSH

use Net::OpenSSH;
my $ssh = Net::OpenSSH->new($host, user => $user, password => $password);
my $output = $ssh->capture($cmd);