파이프된 쉘 스크립트의 Stderr가 항상 표시되지는 않습니다.

파이프된 쉘 스크립트의 Stderr가 항상 표시되지는 않습니다.

나는 내 자신의 쉘 스크립트를 파이핑하여 몇 가지 테스트를 하고 있었는데 이상한 것을 발견했습니다. 즉, 이러한 파이프된 프로세스의 표준 오류가 항상 화면에 표시되는 것은 아닙니다.

스크립트를 단순화했으며 이것은 bash를 사용한 세션입니다.

$ cat file1
echo stdout
echo stderr 1>&2
$ cat file2
echo stdout2
echo stderr2 1>&2
$ cat file3
echo stdout3
echo stderr3 1>&2

$ ./file1 | ./file2 | ./file3
stderr2
stderr
stdout3
stderr3

$ ./file1 | ./file2 | ./file3
stderr
stdout3
stderr3

$ ./file1 | ./file2 | ./file3
stderr2
stdout3
stderr3

file3이 아무것도 읽지 않기 때문에 처음 두 스크립트의 stdout이 손실된다는 것을 알고 있지만 그것은 중요하지 않습니다.

두 번째와 세 번째 경우에 stderr2와 출력은 각각 어떻게 되나요 ?stderr

답변1

아, 경쟁 조건이군요! 이 효과를 생성하기 위해 백그라운드에서 몇 가지 작업이 수행됩니다.

첫째, 프로세스가 다른 쪽 끝에서 닫힌 파이프에 쓰기를 시도하면 프로세스는 신호를 받습니다 SIGPIPE. 기본적으로 프로세스가 종료됩니다. 왜 이것을 원합니까? 를 실행하면 cat my_huge_file | head -3파일의 처음 세 줄만 표시되며 신호 메커니즘 덕분에 cat이 세 줄 이후에 중지되는 것을 알 수 있습니다. 그렇지 않으면 전체 파일을 읽습니다.

둘째, 파이프라인의 모든 프로세스는 병렬로 실행되며 어떤 프로세스가 먼저 완료될지 예측할 수 없습니다. 프로세스가 종료되면 파이프의 읽기 끝을 포함하여 모든 파일 설명자가 닫힙니다.

file3예를 들어, 표준 출력에 쓰기 전에 완전히 완료되는 경우도 있습니다 . file2그런 다음 file2쓰려고 하면 SIGPIPE해당 줄에 도달하지 않고 종료됩니다 echo stderr2. 그러나 다른 경우에는 완료하기 file2전에 stdout에 쓰기를 관리하며 file3, 이 경우 계속할 수 있습니다.

관련 정보