在对变量perl执行openssh时无法捕获stderr [英] unable to capture stderr while performing openssh to a variable- perl

查看:87
本文介绍了在对变量perl执行openssh时无法捕获stderr的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想捕获(ssh->捕获)到变量后在主机上显示的标准错误.

I want to capture the standard error displayed on host machine after (ssh->capture) to a variable.

例如,当我尝试:

  use Net::OpenSSH;

my $ssh = Net::OpenSSH->new($host);
my $out=$ssh->capture("cd /home/geek");
 $ssh->error and
die "remote cd command failed: " . $ssh->error;

输出为:

 child exited with code 1 at ./change_dir.pl line 32

我看不到错误是什么.我在终端上没有这样的文件或目录.我想在$ out中捕获相同的没有这样的文件或目录".

i am not able to see what is the error. i get no such file or directory on the terminal. I want to capture the same "no such file or director" in $out.

示例2,

my ($stdout,$stderr)=$ssh->capture("cd /home/geek");
if($stderr)
print"Error = $stderr";
else
print "$stdout"

我在屏幕上看到"Error =,但没有看到该$ stderr. 我看到$ stdout成功打印,但是print $ stderr不会仅打印"Error =".

i see "Error=" printed but does not seee that $stderr on the screen. i see $stdout is printed on success but print $stderr does not get printed only"Error= " gets printed.

推荐答案

发生错误时,很可能不是会出现在STDOUT中,如果出现在STDERR中,则说明您没有抓住.您需要通过以下方式获取应用程序的退出代码. (给出了我现在才看到的问题的更新:有关如何获得STDERR的信息,请参见结尾.)

When an error occurs it is most likely not going to be in STDOUT, and if it is in STDERR you are not catching that. You need to get to the application's exit code, in the following way. (Given the update to the question which I only see now: See the end for how to get STDERR.)

capture方法之后,您要检查$?是否存在错误(请参阅

After the capture method you want to examine $? for errors (see Net-OpenSSH). Unpack that to get to the exit code returned by what was actually run by $ssh, and then look in that application's docs to see what that code means

$exit_code = $?;
if ($exit_code) {
    $app_exit = $exit_code >> 8; 
    warn "Error, bit-shift \$? --> $app_exit";
}

要研究的代码是$app_exit.

一个例子.我在项目中使用zip,偶尔会捕获到3072(即$?)错误.如上解压后,我得到12,这是zip的实际出口.我查看了它的文档,它很好地列出了退出代码,并且12表示没有任何更新.这是zip的设计决策,如果存档中没有要更新的文件,则退出12.然后,该出口被打包成两个字节的数字(在高字节中),并返回那个,因此我在$?中得到了什么.

An example. I use zip in a project and occasionally catch the error of 3072 (that is the $?). When that's unpacked as above I get 12, which is zip's actual exit. I look up its docs and it nicely lists its exit codes and 12 means Nothing to update. That's the design decision for zip, to exit with 12 if it had no files to update in the archive. Then that exit gets packaged into a two-byte number (in the upper byte), and that is returned and thus what I get in $?.

一般是故障模式,来自Perl文档中的系统

Failure modes in general, from system in Perl docs

if    ($? == -1) { warn "Failed to execute -- " }
elsif ($? & 127) { 
    $msg = sprintf("\tChild died with signal %d, %s coredump -- ",
        ($? & 127),  ($? & 128) ? 'with' : 'without');
    warn $msg;
} else { 
    $msg = sprintf("\tChild exited with value %d -- ", $? >> 8);
    warn $msg;
}

实际的退出代码$? >> 8由任何运行提供,因此其解释取决于该应用程序.您需要查看其文档,并希望记录其退出代码.

The actual exit code $? >> 8 is supplied by whatever ran and so its interpretation is up to that application. You need to look through its docs and hopefully its exit codes are documented.

请注意,$ssh->error似乎是为此任务设计的.来自模块的文档

Note that $ssh->error seems designed for this task. From the module's docs

my $output = $ssh->capture({ timeout => 10 }, "echo hello; sleep 20; echo bye");
$ssh->error and warn "operation didn't complete successfully: ". $ssh->error;

打印的错误需要进一步调查.文档没有说明它是什么,但是我希望上面讨论过的解压缩代码(问题更新表明了这一点).在这里,$ssh仅运行命令,并且不知道出了什么问题.它只是取回命令的退出代码,以供查看.

The printed error needs further investigation. Docs don't say what it is, but I'd expect the unpacked code discussed above (the question update indicates this). Here $ssh only runs a command and it doesn't know what went wrong. It merely gets back the command's exit code, to be looked at.

或者,您可以修改命令以在STDOUT上获取STDERR,如下所示.

Or, you can modify the command to get the STDERR on the STDOUT, see below.

capture方法等效于Perl的反引号(qx).关于如何从反引号中获取STDERR的事情很多,Perl自己的常见问题解答也很好地写下了$ssh运行),以便将其STDERR重定向到其STDOUT.

The capture method is an equivalent of Perl's backticks (qx). There is a lot on SO on how to get STDERR from backticks, and Perl's very own FAQ has that nicely written up in perlfaq8. A complication here is that this isn't qx but a module's method and, more importantly, it runs on another machine. However, the "output redirection" method should still work without modifications. The command (run by $ssh) can be written so that its STDERR is redirected to its STDOUT.

$cmd_all_output = 'your_whole_command 2>&1';
$ssh->capture($cmd_all_output);

现在,您会看到在STDOUT上显示的终端上看到的错误(无此类文件或目录"),因此该错误会出现在$stdout中.请注意,如上所述,必须使用sh shell语法.它还有很多其他功能,因此请查找一下(但这应该可以正常使用).在大多数情况下,它与退出代码说明中的消息相同.

Now you will get the error that you see at the terminal ("no such file or directory") printed on STDOUT, thus it will wind up in your $stdout. Note that one must use sh shell syntax, as above. There is a big bit more to it so please look it up (but this should work as it stands). Most of the time it is the same message as in the exit code description.

代码中的检查是好的,第一道防线:运行外部命令时,应始终检查$?,为此,无需触摸要运行的命令

The check that you have in your code is good, the first line of defense: One should always check $? when running external commands, and for this the command to run need not be touched.

这篇关于在对变量perl执行openssh时无法捕获stderr的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆