development

Perl에서 stderr, stdout 및 종료 코드를 한꺼번에 캡처하는 방법은 무엇입니까?

big-blog 2020. 12. 30. 20:14
반응형

Perl에서 stderr, stdout 및 종료 코드를 한꺼번에 캡처하는 방법은 무엇입니까?


Perl에서 외부 프로세스를 실행하고 stderr, stdout 및 프로세스 종료 코드를 캡처 할 수 있습니까?

예를 들어 백틱을 사용하여 stdout을 얻고 IPC :: Open3을 사용하여 출력을 캡처하고 system ()을 사용하여 종료 코드를 얻는 등 이러한 조합을 수행 할 수있는 것 같습니다.

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


IPC :: Open3에 대한 문서를 다시 읽으면 자식 프로세스를 얻기 위해 waitpid호출해야한다는 메모가 표시 됩니다. 이렇게하면에서 상태를 확인할 수 있습니다 $?. 종료 값은 $? >> 8입니다. $?perldoc perlvar를 참조하십시오 .


( 업데이트 : 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 출력 또는 외부 프로그램의 출력을 캡처하는 데 사용할 수있는보다 일반적인 capture () 함수도 있습니다. 따라서 일부 Perl 모듈이 외부 프로그램을 사용하는 경우에도 여전히 출력을 얻습니다.

또한 외부 프로그램에 IPC :: Open3을 사용하고 Perl 출력을 캡처하는 다른 모듈을 사용하는 대신 STDOUT 및 STDERR을 캡처 (또는 병합)하는 단일 접근 방식 만 기억하면됩니다.


STDERR의 내용을 원하지 않는 경우 IPC :: System :: Simple 모듈 의 capture () 명령 은 거의 정확히 다음과 같습니다.

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

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

   my $exit_value = $EXITVAL;

단일 인수와 함께 capture ()를 사용하여 쉘을 호출하거나 다중 인수를 사용하여 쉘을 안정적으로 피할 수 있습니다. 또한 단일 인수로도 쉘을 호출하지 않는 capturex ()도 있습니다.

Perl의 기본 제공 시스템 및 백틱 명령과 달리 IPC :: System :: Simple은 Windows에서 전체 32 비트 종료 값을 반환합니다. 또한 명령을 시작할 수 없거나 신호로 죽거나 예상치 못한 종료 값을 반환하는 경우 자세한 예외가 발생합니다. 즉, 많은 프로그램에서 직접 종료 값을 확인하는 대신 IPC :: System :: Simple에 의존하여 어려운 작업을 수행 할 수 있습니다.

 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 :: System :: Simple은 순수 Perl이며 종속성이 없으며 Unix 및 Windows 시스템에서 모두 작동합니다. 불행히도 STDERR 캡처 방법을 제공하지 않으므로 모든 요구 사항에 적합하지 않을 수 있습니다.

IPC :: Run3 은 세 가지 일반적인 파일 핸들을 모두 다시 연결하는 깔끔하고 쉬운 인터페이스를 제공하지만 불행히도 명령이 성공했는지 확인하지 않으므로 $? 전혀 재미가 없습니다. $ 검사를위한 공용 인터페이스 제공? $ 검사 이후 IPC :: System :: Simple에 대한 할 일 목록 에있는 것이 무엇 입니까? 크로스 플랫폼 방식은 내가 누구에게도 바라는 일이 아닙니다.

IPC :: 네임 스페이스에는 지원을 제공 할 수 있는 다른 모듈 이 있습니다. YMMV.

모두 제일 좋다,


외부 명령을 실행하는 세 가지 기본 방법이 있습니다.

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

으로 system(), 모두 STDOUT와 STDERR 스크립트의 같은 장소를 갈 것입니다 STDOUTSTDERR,하지 않는 한 system()명령 리디렉션 그들. 백틱하고 명령 open()만 읽습니다 STDOUT.

open으로 다음과 같이 호출하여 STDOUTSTDERR.

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

반환 코드는 항상 @Michael Carman에$? 의해 기록 된대로 저장됩니다 .


정말 복잡해지면 Expect.pm을 사용해보세요. 그러나 프로세스에 입력을 보내는 것도 관리 할 필요가 없다면 과잉 일 것입니다.


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

참조 URL : https://stackoverflow.com/questions/109124/how-do-you-capture-stderr-stdout-and-the-exit-code-all-at-once-in-perl

반응형