2015-02-10 50 views
1

对于我来说,在Perl中通常足以让包含STDOUT和STDERR的单个字符串。我这样做:Perl:与STDOUT分开获取系统调用的STDERR

my $stdout_and_stderr = `$cmd 2>&1`; 

但现在我需要它在2个单独的字符串 - 一个用于标准输出和一个用于STDERR。

我该怎么在Perl中做到这一点?

回答

2
use IPC::Run3 qw(run3); 
run3 [ 'sh', '-c', $cmd ], undef, my $stdout, my $stderr; 
0

这里是一个例子。

#!/usr/bin/perl 
use warnings; 
use strict; 
use IPC::Open3; 

my $cmd = 'ls -la'; 

my $pid = open3(\*WRITER, \*READER, \*ERROR, $cmd); 
#if \*ERROR is 0, stderr goes to stdout 

while(my $output = <READER>) 
{ 
    print "output->$output"; 
} 

while(my $errout = <ERROR>) 
{ 
    print "err->$errout"; 
} 

waitpid($pid, 0) or die "$!\n"; 
my $retval = $?; 
print "retval-> $retval\n"; 
+0

谢谢!很棒。另外感谢你的详细和完整的例子 – SomethingSomething 2015-02-10 08:57:25

+2

这个程序患有竞争条件。如果孩子输出很多STDERR,两个程序都会锁定。改为使用IPC :: Run3或IPC :: Run。 – ikegami 2015-02-10 15:43:01

+0

@ikegami,谢谢你的重要提示。你可以在这里写下你的解决方案吗? – SomethingSomething 2015-02-11 08:19:33

0

其实我发现了一个更简单的方法只捕获STDERR。抓STDERR扔STDOUT远:

$output = `cmd 2>&1 1>/dev/null`; 

你也可以做相反的事情 - 扔STDERR远,使得它甚至没有印到shell:

$output = `cmd 2>/dev/null`; 

如果您需要捕捉两个他们分开,在这个线程中使用其他答案之一。他们非常好

+0

虽然这并不回答这个问题(因此不应该被接受的答案)。问题是如何分别捕获STDOUT和STDERR。你的回答忽略STDOUT,只捕获STDERR。 – 2015-09-11 23:13:08

+0

你说得对。相应地更改了接受的答案 – SomethingSomething 2015-09-12 18:43:57