我想从我的Perl脚本中执行外部命令,将stdout和stderr的输出放入我选择的$variable
中,并将命令的退出代码放入$?
变量中
我在perlfaq8和他们的论坛中找到了解决方案,但他们并没有为我工作。奇怪的是,只要退出代码是正确的,我就不会获取sdterr的输出。
我在Red Hat Linux 5上使用Perl版本5.8.8。
这是我正在尝试的一个例子:
my $cmd="less";
my $out=`$cmd 2>&1`;
或
my $out=qx($cmd 2>&1);
或
open(PIPE, "$cmd 2>&1|");
当命令成功运行时,我可以捕获stdout。
我不想使用其他捕获模块。如何捕获外部命令的完整结果?
答案 0 :(得分:9)
这正是David Golden撰写Capture::Tiny
时面临的挑战。我认为它可以帮助您完全满足您的需求。
基本示例:
#!/usr/bin/env perl
use strict;
use warnings;
use Capture::Tiny 'capture';
my ($stdout, $stderr, $return) = capture {
system( 'echo Hello' );
};
print "STDOUT: $stdout\n";
print "STDERR: $stderr\n";
print "Return: $return\n";
重读后你可能真的希望capture_merged
将STDOUT和STDERR加入到一个变量中,但我给出的例子很好而且一般,所以我会离开它。
答案 1 :(得分:5)
实际上,写这个的正确方法是:
#!/usr/bin/perl
$cmd = 'lsss';
my $out=qx($cmd 2>&1);
my $r_c=$?;
print "output was $out\n";
print "return code = ", $r_c, "\n";
如果没有错误,你会得到'0',如果错误,你会得到'-1'。
答案 2 :(得分:4)
STDERR
旨在用于可能需要与STDOUT
输出流分离的错误或消息。因此,我不希望STDERR
等命令的输出中有任何less
。
如果你想要两个(或者任何一个)流和返回代码,你可以这样做:
my $out=qx($cmd 2>&1);
my $r_c=$?
print "output was $out\n";
print "return code = ", $r_c == -1 ? $r_c : $r_c>>8, "\n";
如果命令不可执行(可能是因为您打算使用less
而是编写lsss
),则返回码为-1。否则,正确的退出值是高8位。请参阅system。
答案 3 :(得分:1)
这个问题经常给出的答案是使用包含shell类型重定向的命令行。但是,假设您要避免这种情况,并将open()与命令和参数列表一起使用,因此您不必担心shell如何解释输入(可能部分由用户提供的值组成)。然后不使用IPC :: Open3等软件包,以下内容将同时读取stdout和stderr:
my ($child_pid, $child_rc);
unless ($child_pid = open(OUTPUT, '-|')) {
open(STDERR, ">&STDOUT");
exec('program', 'with', 'arguments');
die "ERROR: Could not execute program: $!";
}
waitpid($child_pid, 0);
$child_rc = $? >> 8;
while (<OUTPUT>) {
# Do something with it
}
close(OUTPUT);