2017-11-04 18 views
0

나는 다음과 같은 스크립트가 :바이너리가 죽으면 "tee /tmp/my.log | my-binary"가 바로 종료되지 않는 이유는 무엇입니까?

#!/bin/bash 
set -e 
set -o pipefail 
tee /tmp/my.log | my-binary 

my-script.sh ... 다음과 같이 실행 : 내 바이너리 충돌하거나 사망 할 때

$ cat my-data.txt | my-script.sh 

내가 가정을, tee 사본은 즉시 종료해야합니다. 그러나 쉘 자체가 종료되는 동안 tee은 그렇지 않습니다.

+1

: tee를 죽이는 즉시 당신이 bash는 4.4 이상을 실행하고, 중요한 경우


, 내가 대신 다음 구현을 제안한다. 특정 신호가있는 "Kill it"? my-binary가 종료가 아닌 다른 방식으로 신호를 처리하도록 선택하면 신호가 트랩 될 수 있습니다. –

+0

(BTW,'pipefail'는 * tee *가 실패했지만 * my-binary *가 성공으로 끝나면 종료 상태가 실패했음을 확인합니다. 그러나 실패한 'my-binary'일 경우'pipefail'은 아무런 효과가 없습니다). –

+0

... 대부분의 상황에서 [이식성 문제] (https://www.in-ulm.de/~mascheck/various/set-e/)의 출처이기는하지만'set -e'는 관련이 없습니다.) 및 [general nonintuitiveness] (http://mywiki.wooledge.org/BashFAQ/105) (서두르면 우화를 건너 뛰고 연습 문제를 참조하십시오). –

답변

1

The POSIX specification for tee은 지정된 피연산자 (예 : /tmp/my.log)에 대한 쓰기가 실패하면 tee 명령이 다른 출력에 계속 쓰기를 지정하도록 지정합니다.

이 사양을 충족시키기 위해 GNU 구현과 Busybox를 포함하여 tee의 일반적인 구현은 SIGPIPE를 완전히 무시합니다. 이렇게하면 /tmp/my.log이 조기에 닫힌 명명 된 파이프 인 경우에도 작업을 계속할 수 있습니다. SIGPIPE 신호의 부작용으로

는 - 오히려 단지 통지 이후 my-binary의 표준 입력 출력이 닫히면 tee 즉시 통보하지 않고 무시되지만되는 -는 FIFO의 타단 중단하기 때 수신 시도가 실패하면. 다른 사람이 문제를 재현하게하는 것만으로는 충분하지 않습니다

#!/usr/bin/env bash 

# replace stdin with a pipe from tee 
exec < <(tee /tmp/my.log) 

# collect PID for the process substitution; REQUIRES BASH 4.4 OR NEWER 
tee_pid=$! 
trap 'kill "$tee_pid"' EXIT 

my-binary