2012-01-04 11 views
4

私のPerlスクリプトからstdoutとstderrの両方の出力を私の選択した$variableに入れて、コマンドの終了コードを$?変数に追加します。perlの外部* nixコマンドからのSTDOUT、STDERR、レスポンスコードの取得

私は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|"); 

dが正常に実行され、私はstdoutをキャプチャできます。

追加のキャプチャモジュールは使用しません。外部コマンドの完全な結果をどのようにキャプチャできますか?

+0

だけ使用[IPC ::ファイル名を指定して実行](https://metacpan.org/module/IPC::Run:次に、このようなIPC ::のopen3としてパッケージに頼ることなく、次のようにstdoutとstderrの両方を読み込みます)これはこれを簡単にします。 –

+0

関連:http://stackoverflow.com/q/3263912/2157640 – Palec

答えて

4

は実際に、これを書くための適切な方法は次のとおりです。

#!/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」します。

4

STDERRSTDOUT出力ストリームから分離する必要がある場合がありますエラーやメッセージに使用されることを意図しています。したがって、私はlessのようなコマンドの出力から何もSTDERRを期待しません。あなたは、両方(またはいずれか)ストリームとリターンコードが必要な場合

、あなたができる:

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を参照してください。

8

これはDavid GoldenがCapture::Tinyと書いたときに直面した挑戦でした。私はそれがあなたが必要とするものを正確に行うのに役立つと思います。

Basicの例:あなたを再読み込みした後

#!/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

よくある質問は、シェルタイプのリダイレクトを含むコマンドラインを使用することです。しかし、あなたはそれを避け、コマンドと引数リストでopen()を使いたいので、シェルがどのように入力を解釈するかについては心配する必要はありません(ユーザが提供する値で部分的に構成されているかもしれません)。

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); 
+0

これはこのスレッドでの最良の回答です。より多くのコードでは、シェルリダイレクトの使用を防ぎますが、通常bashです。この例は、あなたがコメントしてくれればより良いでしょう。それはperldocオープン関数で詳しく記述されています。 – Znik

+0

重要な質問があります。なぜ、最初に子プロセスを待ってRCをチェックするのですか?その後、その出力を読みますか?私はそれを交換する必要があります。私はそれが正常に動作する唯一の理由だと思う、それはオペレーティングシステムによって作られたパイプバッファリングです。ストリームのリダイレクトのために、外部の 'プログラム'がstdoutまたはstderrで大きなストリームを生成すると、ハングします。 – Znik

関連する問題