꼬리 로그의 다중 파이프 - 마지막 파이프는 stdin을 수신하지 않습니다.

꼬리 로그의 다중 파이프 - 마지막 파이프는 stdin을 수신하지 않습니다.

나는 우분투에서 흥미로운 상태에 빠졌습니다. 아래 단계가 이를 가장 잘 설명합니다.

하나의 파이프로 내가 기대하는 것을 보고 있습니다.

# In shell A
tail -f foo.log | grep aaa

# In shell B
echo aaa >> foo.log

# Shell A prints out `aaa`

하지만 여러 파이프를 사용하면 전혀 아무것도 표시되지 않습니다.

# In shell A
tail -f foo.log | grep aaa | grep bbb

# In shell B
echo aaa bbb >> foo.log

# Nothing ever prints in shell A

하지만 그냥 에코만 하면 괜찮습니다.

echo 'aaa bbb' | grep aaa | grep bbb

이것은 최소한의 재생산을 만들기 위한 나의 시도입니다. 처음에는 adb logcat(Android 개발 도구)에서 로그를 티링하려고 할 때 문제가 발생했습니다. 나는 zsh, bash 및 fish에서도 시도했습니다.

나는 그것이 내 inotify 감시자 제한과 관련이 있다고 생각했지만 부딪혀도 아무 것도 바뀌지 않았습니다.

답변1

이는 일반적으로 라인에 신경 쓰지 않고 데이터를 축적할 수 있는 파이프의 버퍼링 때문입니다.

tail -f나는 라인 버퍼링을 그 자체로 사용한다고 생각합니다 . 마지막은 greptty에 쓰기 때문에 라인 버퍼링도 사용합니다. 따라서 첫 번째 예제가 작동합니다.

하지만 grep중간에는 다르므로 라인 버퍼링을 강제하거나 버퍼링을 비활성화하여 동작을 조정해야 합니다. 다음 명령은 예상대로 작동합니다.

  • grep귀하가 지원하는 경우 --line-buffered(Ubuntu에서는 지원됩니다):

      tail -f foo.log | grep --line-buffered aaa | grep bbb
    
  • 보다 일반적인 솔루션(이외의 많은 필터와 함께 작동 grep):

      tail -f foo.log | unbuffer -p grep aaa | grep bbb
      tail -f foo.log | stdbuf -oL grep aaa | grep bbb
      tail -f foo.log | stdbuf -o0 grep aaa | grep bbb
    

자세한 내용과 특이한 점은 및 를 man 1 grep참조 하세요 .man 1 unbufferman 1 stdbuf

노트:

  • 두 솔루션 모두 이식 가능하지 않습니다( grep --line-buffered및 POSIX에서 지정되지 않음).unbufferstdbuf
  • 당신이 이것을 할 수 있다면 grep --line-buffered그것은 당신의 선택이어야 합니다. 추가 도구를 사용해도 소용이 없습니다.
  • Unix 및 Linux SE 관련 질문:파이프에서 버퍼링 끄기.
  • unbuffer그리고stdbuf 완전히 다른 방식으로 일하다.
  • 를 사용하면 여기서는 버퍼링 없음 stdbuf( )보다 라인 버퍼링 -oL( )을 선호해야 합니다 .-o0
    • 성능이 더 좋을 가능성이 높습니다.
    • 어쨌든 파이프의 다른 부분에서는 라인 버퍼링을 사용합니다.
  • 마지막으로 grep다른 파일에 쓴 경우 다른 파일처럼 작동합니다 grep. 이러한 경우 최종 파일에 행이 즉시 나타나도록 하려면 마지막 grep.
  • 에서 가 래퍼 함수인 fish경우 로 원하는 동작을 얻지 못할 수 있습니다 . 사용 . 이 질문을 참조하세요:grep--line-bufferedcommand grep --line-buffered출력 파이프는 EOF를 기다립니다.fish.

참고 사항: tail foo.log | grep aaa | grep bbb(예: tail없음 -f)은 종료되기 때문에 문제를 일으키지 않습니다 tail. 종료 되면 tail첫 번째는 grepEOF를 감지하고 버퍼를 플러시하고 종료한 다음 두 번째도 grep동일한 작업을 수행합니다.

관련 정보