2015-02-10 53 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