나는 프로그램의 출력을 while read VAR
루프로 파이프하고 break
패턴이 발견되면 출력할 계획이었지만 그렇지 않았습니다.
개념의 증거:
inotifywait -qm -e create . | while read line; do echo $line; break; done
./ CREATE newfile
..
tail -f /var/log/syslog | while read line; do echo $line; break; done
Nov 6 22:44:05 section9 ntpdate[2381]: adjust time server 91.189.89.199 offset 0.272779 sec
소스 프로그램이 무엇을 출력하든 종료되지 않습니다. 사전 설정은 set -x
루프가 두 번째 이후 반복되지 않음을 나타냅니다 read
. $BASH_SUBSHELL
이 예에서는 1입니다.
tail
inotifywait
등. SIGPIPE를 받고 종료하면 안되는 건가요 ?
프로세스 대체( while read ... break; done < <(tail -f ...)
)가 제대로 작동한다는 점에 유의하세요. $BASH_SUBSHELL
이 경우에는 0입니다.
답변1
요점은 bash(다른 쉘은 다를 수 있음)에서 파이프가 종료될 때까지 종료되지 않는다는 것입니다.모든 명령파이프라인에서 완료되었습니다.
이해하기 위해 다음을 고려해 봅시다:
inotifywait -qm -e create . | while read line; do echo $line; break; done
한 줄을 읽으면 read
에코된 후 break
실행되고 마지막으로 프로세스가 종료됩니다. 그러나 첫 번째 프로세스는 표준 출력 쓰기에 실패할 때까지 계속됩니다. 따라서 루프는 적어도 inotifywait
해당 항목에 쓰기를 시도할 때까지 계속됩니다.두번째출력 라인. 버퍼링의 모호함으로 인해 이런 일이 발생하지 않을 수도 있습니다. 검색이 발생하려면 여러 줄이 필요할 수 있습니다. 쓰기 시도가 실패하면 SIGPIPE가 발행됩니다.
이제 또 다른 시나리오를 고려해보세요.
while read line; do echo $line; break; done < <(inotifywait -qm -e create .)
여기에는 파이프가 없습니다. break
실행 되면 while
루프가 완료됩니다.
문서
"파이프라인" 섹션에서 man bash
:
껍데기모든 명령을 기다립니다파이프에서 종료 중...
이 행동은 당신이 내리는 선택입니다 bash
. POSIX에서는 이를 의무화하지 않습니다. POSIX상태:
파이프가 백그라운드에 있지 않은 경우(비동기 목록 참조), 쉘은 파이프에 지정된 마지막 명령이 완료될 때까지 기다려야 합니다.기다릴 수도 있다모든 명령을 완료하려면
답변2
strace tail -f -n 5000 /var/log/messages |
while read line; do echo $line; break; done;
무슨 일이 일어났는지 자세히 보여줍니다.
[...]
write(1, "Nov 1 22:20:01 inno systemd[1]:"..., 4096) = 4096
즉, tail은 한 번에 최대 4096바이트를 파이프에 쓸 수 있습니다(파이프가 버퍼링할 수 있는 용량). 데이터가 그다지 많지 않은 경우가 많습니다 tail
.
strace tail -f /var/log/messages | while read line; do echo $line; break; done;
프로그램
write(1, "Nov 7 07:00:02 inno systemd[1]:"..., 730) = 730
따라서 tail
파일에 무언가가 추가될 때까지 다시 쓰기를 시도하지 않습니다.
나는 unbuffer
이것이 해결될 수 있다고 생각했다. 나는 그렇지 않다는 것에 놀랐다.
unbuffer tail -f file1 | while read line; do echo $line; break; done