2008-09-20 3 views
56

Perl에서 외부 프로세스를 실행하고 stderr를 캡처하고 stdout을 처리 종료 코드로 캡처 할 수 있습니까?Perl에서 stderr, stdout 및 exit 코드를 한꺼번에 캡처하는 방법은 무엇입니까?

나는 이들의 조합을 수행 할 수있는 것으로 보인다. backdicks를 사용하여 stdout을 얻고 IPC :: Open3은 출력을 캡처하고 system()은 종료 코드를 얻습니다.

stderr, stdout 및 exit 코드를 한 번에 모두 캡처하는 방법은 무엇입니까?

답변

26

IPC :: Open3에 대한 설명서를 다시 읽으면 waitpid으로 전화하여 자식 프로세스를 얻을 수 있다는 메모가 표시됩니다. 이렇게하면 $?에 상태를 사용할 수 있습니다. 이탈 값은 $? >> 8입니다. $? in perldoc perlvar을 참조하십시오. system()

system $cmd;  # using system() 
$output = `$cmd`;  # using backticks (``) 
open (PIPE, "cmd |"); # using open() 

, 모두 STDOUT 및 STDERR system() 명령을 리디렉션하지 않는 스크립트의 STDOUTSTDERR, 같은 곳을 갈 것입니다 : 외부 명령을 실행하는 세 가지 기본 방법이

+1

왜 링크가 엉망인지 모르겠다. 편집/미리보기에서 모든 것이 잘 보입니다. –

+2

perl5porters에게 IPC :: Open2 및 :: Open3에 패치를 보내서 해당 모듈의 구문에 waitpid 항목을 표시합니다. :) –

7

있습니다. 역주와 open() 읽기 전용 STDOUT 명령.

STDOUTSTDERR을 모두 리디렉션하려면 open과 함께 다음과 같이 호출 할 수도 있습니다. @Michael Carman에서 언급 한 바와 같이

open(PIPE, "cmd 2>&1 |"); 

는 리턴 코드는 항상 $?에 저장됩니다.

+0

'qx //' –

41

(업데이트 :이 더 쉽게하기 위해 IO :: CaptureOutput에 대한 API를 업데이트했습니다.)이 작업을 수행하는 방법은 여러 가지가 있습니다

. 여기에 하나의 옵션은 IO::CaptureOutput 모듈 사용의 :

use IO::CaptureOutput qw/capture_exec/; 

my ($stdout, $stderr, $success, $exit_code) = capture_exec(@cmd); 

이는 capture_exec() 함수를하지만, IO :: CaptureOutput도에서 펄 출력 또는 출력을 캡처하는 데 사용할 수있는 일반적인 캡처() 함수를 가지고 외부 프로그램. 따라서 일부 Perl 모듈이 일부 외부 프로그램을 사용하는 경우에도 출력을 얻을 수 있습니다.

외부 프로그램 용 IPC :: Open3 및 Perl 출력 캡처 용 모듈을 사용하는 대신 STDOUT 및 STDERR을 캡처 (또는 병합)하는 단일 접근법 하나만 기억하면됩니다. 당신이 STDERR의 내용을 원하지 않는 경우

+12

을 잊지 마세요 [Capture :: Tiny] (http://search.cpan.org/dist/Capture-Tiny/)가 더 새롭고 더 좋습니다. '이 모듈은 영감을 받았습니다 IO :: CaptureOutput에 의해 출력을 티밍하고보다 복잡한 코드와 API없이 비슷한 기능을 제공합니다. IO :: CaptureOutput은 "제한 사항"절에서 설명한 레이어 또는 대부분의 비정상적인 경우를 처리하지 않으므로 더 이상 권장하지 않습니다. ' - http://search.cpan.org/~dagolden/Capture-Tiny-0.18/lib/Capture/Tiny.pm#SEE_ALSO –

+0

사용 예제는 http://stackoverflow.com/a/8781408/110126을 참조하십시오. 캡처 :: 작은. – buzz3791

+5

@PhilipDurbin이 답변의 저자는 Capture :: Tiny의 저자와 같은 사람입니다. :) – simbabque

14

, 다음 IPC::System::Simple 모듈에서 캡처() 명령은 거의 정확하게 당신이있어 무엇 후 : 하나의 인수를

use IPC::System::Simple qw(capture system $EXITVAL); 

    my $output = capture($cmd, @args); 

    my $exit_value = $EXITVAL; 

당신이 사용할 수있는 캡처() 셸을 호출하거나 여러 개의 인수를 사용하여 셸을 확실하게 피할 수 있습니다. 하나의 인수로도 쉘을 호출하지 않는 capturex()도 있습니다.

Perl의 기본 제공 시스템 및 백틱 명령과 달리 IPC :: System :: Simple은 Windows에서 전체 32 비트 종료 값을 반환합니다. 또한 명령을 시작할 수 없거나 신호가 끊어 지거나 예기치 않은 종료 값을 반환하는 경우에도 자세한 예외가 발생합니다.이것은 당신이 IPC :: 시스템에 의존하는 수 많은 프로그램, 오히려 출구가 자신의 가치를 확인하는 것보다 의미 : 당신을위한 노력을 할 간단한 :

use IPC::System::Simple qw(system capture $EXIT_ANY); 

system([0,1], "frobincate", @files);  # Must return exitval 0 or 1 

my @lines = capture($EXIT_ANY, "baznicate", @files); # Any exitval is OK. 

foreach my $record (@lines) { 
    system([0, 32], "barnicate", $record); # Must return exitval 0 or 32 
} 

IPC :: 시스템 : 간단한 순수하다 Perl은 의존성이 없으며 Unix 및 Windows 시스템에서 작동합니다. 불행히도 STDERR을 캡처하는 방법을 제공하지 않으므로 모든 요구 사항에 적합하지 않을 수 있습니다.

IPC::Run3은 세 가지 공통 파일 핸들을 모두 다시 배관 할 수있는 깨끗하고 쉬운 인터페이스를 제공하지만 불행히도 명령이 성공했는지 확인하지 않으므로 $? 수동으로, 이것은 전혀 재미 있지 않습니다. $를 검사하기위한 공용 인터페이스 제공? $ 012를 검사 한 이래로 IPC :: System :: Simple에 대한 나의 to-do list에있는 것입니다. 크로스 플랫폼 방식으로 나는 누군가에게 바라는 일이 아니다.

IPC:: 네임 스페이스에는 다른 모듈이있어 도움을받을 수 있습니다. YMMV.

모든 최선을,

+0

기술적으로 Win32 :: Process가 필요한 Windows에서만 의존성이 있습니다. 이것이 Perl의 핵심은 아니지만 ActiveState Perl 및 Strawberry Perl 배포본에 번들로 제공됩니다. – xdg

+0

+1, 나는 IPC :: System :: Simple을 항상 사용한다. – Ether

0

당신이 정말로 복잡 받고 있다면, 당신은 Expect.pm을 시도 할 수도 있습니다. 하지만 프로세스에 대한 입력을 관리 할 필요가 없다면 과장 될 수 있습니다.

0

IPC:run3이 매우 유용합니다. 모든 하위 파이프를 glob 또는 변수로 전달할 수 있습니다. 아주 쉽게! 종료 코드는 $?에 저장됩니다.

다음은 제가 숫자가 될 것임을 알고있는 stderr를 얻은 방법입니다. cmd는 stdout으로 정보 변환을 출력하고 (> args의 파일에 파이프를 사용하여>) STDERR로 변환 한 수를보고합니다.

use IPC::Run3 

my $number; 
my $run = run3("cmd arg1 arg2 >output_file",\undef, \undef, \$number); 
die "Command failed: $!" unless ($run && $? == 0); 
관련 문제