나는 내 자신의 쉘 스크립트를 파이핑하여 몇 가지 테스트를 하고 있었는데 이상한 것을 발견했습니다. 즉, 이러한 파이프된 프로세스의 표준 오류가 항상 화면에 표시되는 것은 아닙니다.
스크립트를 단순화했으며 이것은 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
, 이 경우 계속할 수 있습니다.