Perl에서 stderr, stdout 및 종료 코드를 동시에 어떻게 캡처합니까?

StackOverflow https://stackoverflow.com/questions/109124

  •  01-07-2019
  •  | 
  •  

문제

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

나는 이것들의 조합을 할 수 있는 것 같습니다.백틱을 사용하여 stdout을 가져오고, IPC::Open3을 사용하여 출력을 캡처하고, system()을 사용하여 종료 코드를 가져옵니다.

stderr, stdout 및 종료 코드를 한 번에 어떻게 캡처합니까?

도움이 되었습니까?

해결책

IPC::Open3에 대한 문서를 다시 읽으면 호출해야 한다는 메모가 표시됩니다. 기다려 자식 프로세스를 수확합니다.이 작업을 수행하면 상태가 다음에서 사용 가능해야 합니다. $?.종료 값은 $? >> 8.보다$? 펄독에서 펄바르.

다른 팁

(업데이트:이를 더욱 쉽게 만들기 위해 IO::CaptureOutput용 API를 업데이트했습니다.)

이를 수행하는 방법에는 여러 가지가 있습니다.여기에 하나의 옵션이 있습니다. IO::캡처출력 기준 치수:

use IO::CaptureOutput qw/capture_exec/;

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

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

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

STDERR의 내용을 원하지 않으면 다음의 Capture() 명령을 사용하십시오. IPC::시스템::단순 모듈은 당신이 추구하는 것과 거의 정확히 같습니다:

   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 :: System :: 간단한 일을 할 수 있습니다.

 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::런3 세 가지 공통 파일 핸들을 모두 다시 연결하는 깨끗하고 쉬운 인터페이스를 제공하지만 불행히도 명령이 성공했는지 확인하지 않으므로 $?수동으로 하는 것은 전혀 재미가 없습니다.$?를 검사하기 위한 공개 인터페이스 제공?내 일이야 할 일 목록 IPC::System::Simple의 경우 $?를 검사한 이후크로스 플랫폼 방식으로 작업하는 것은 누구에게도 바라는 작업이 아닙니다.

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

모두 제일 좋다,

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

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

와 함께 system(), 둘 다 STDOUT STDERR은 스크립트와 같은 위치로 이동합니다. STDOUT 그리고 STDERR, 않는 한 system() 명령이 리디렉션됩니다.백틱 및 open() 만 읽으세요 STDOUT 당신의 명령에 따라.

open을 사용하여 다음과 같이 호출하여 두 가지를 모두 리디렉션할 수도 있습니다. STDOUT 그리고 STDERR.

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

반환 코드는 항상 다음 위치에 저장됩니다. $? 에 의해 언급된 바와 같이 @마이클 카먼.

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

나는 찾았다 IPC:실행3 매우 도움이 될 것입니다.모든 하위 파이프를 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);
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top