Linux FIFO 버퍼링은 판독기와 기록기가 호출되는 순서에 따라 달라집니다.

Linux FIFO 버퍼링은 판독기와 기록기가 호출되는 순서에 따라 달라집니다.

저는 fifo에서 읽고 다른 fifo에 쓰는 간단한 Python 스크립트를 작성하려고 합니다.

다음 명령을 사용하여 두 개의 FIFO를 생성했습니다.

$ mkfifo input
$ mkfifo output

다음 명령을 사용하여 스크립트를 호출합니다.

$ tail -f input | stdbuf -oL ../entropyCalc/entropy.py > output

, 다음 명령을 사용하여 FIFO를 관찰합니다 output.

$ tail -f output

그런 다음 작가에게 다음과 같이 전화하십시오.

$ echo "/path/to/a/valid/file" >> input

문제는 fifo가 입력 파일을 처리한 후 즉시 결과를 출력하기를 원하지만 스크립트를 한 번 호출(실행)할 때 스크립트를 종료한 다음 다시 실행하는 것만 관찰한다는 것입니다. 그 후에는 모든 것이 잘 작동합니다.

요약: 스크립트 실행 -> 리더 시작 -> fifo에 쓰기를 실행하면
리더에 출력이 표시되지 않습니다. 그러나 스크립트 실행 -> 리더 시작 -> fifo에 쓰기 명령은 출력을 수행합니다. 결과 -> 스크립트 종료 -> 스크립트 재실행input
tail -f output

결과가 stdout에 기록된 후 시스템이 즉시 파일에 기록하기를 원하기 때문에 이 동작의 원인이 무엇인지 잘 모르겠습니다. stdbuf -oL버퍼링을 한 줄로 제한하는 버퍼링을 사용하지 않으면 버퍼링이 발생할 것으로 예상됩니다.

Python 스크립트는 간단한 엔트로피 계산기입니다.

#! /usr/bin/env python2

import sys, os
import numpy as np
from scipy.stats import entropy

while 1:
    try:
        line = sys.stdin.readline()
    except KeyboardInterrupt:
        break

    if not line:
        break

    line = line.strip()

    if not line == '':
        fname1 = open(line)
        fsize = os.path.getsize(line)
        f1 = np.frombuffer(fname1.read(fsize), dtype=np.uint8)
        value,counts = np.unique(f1, return_counts=True)
        print line,str(entropy(counts))
        sys.stdout.flush()

Ubuntu 18.04.3에서 bash 4.4를 사용하고 있습니다.

답변1

당신은 tail그것을 잘못 사용했습니다.

당신이 관찰하는 것은 단순히 나타냅니다tail -f output광고 한 것과 같이. 그리고 당신이 사용하는 함정이 더 많습니다 tail -f input.

이러한 tail오용으로 인해 스크립트의 작동 무결성이 손상될 수도 있습니다. 자세한 내용은 아래를 참조하세요...

간단한 설명

사용 관련 질문 tail -f input:

  • 먼저 파일의 끝을 기다립니다.
  • 파일이 끝나면첫 번째도달하면(첫 번째 파일 이름 공급자가 종료됨) 마지막 10개의 파일 이름만 스크립트에 전달하여 작동 무결성을 파괴합니다.
  • 도달할 때까지 버퍼링됩니다.파일 끝으로 인해 대화형/희소 파일 이름 입력을 사용할 수 없습니다.

사용 관련 질문 tail -f output:

  • 먼저 파일의 끝을 기다립니다.
  • 파일이 끝나면첫 번째도달하면(처음 스크립트가 종료될 때) 지금까지의 스크립트 출력의 마지막 10줄만 제공되어 작동 무결성이 파괴됩니다.

tail -f output( 출력 레그가 터미널이므로 버퍼링은 문제가 되지 않습니다 )

바라보다결론적으로다음은 해결 방법입니다.

긴 설명

직업 설명은 tail기본적으로 다음과 같습니다: "이전 10줄 출력파일 끝". -f스위치는 "만 추가합니다.이후에 추가된 모든 내용".

  • 주요 목표를 달성하려면 tail파일 끝에 도달할 때까지 입력을 조용하고 끝없이 읽어야 합니다(최근 10줄만 버퍼에 유지됨). 그런 다음 버퍼의 마지막 10개 라인을 출력으로 덤프한 다음 종료합니다(또는 동일한 -f작업을 계속합니다).

이제 상기시켜 드리겠습니다.파일이 다음으로 끝남관로업스트림 프로그램이 종료될 때까지 발생하지 않습니다.1 ...

결과는 tail -f output의지이다,디자인에 의해, 아무것도 내보내지 않고 스크립트 결과를 자동으로 버퍼링합니다... 처음으로 스크립트를 종료하는 순간까지: 파일의 끝이 전송되고 tail -f output, 이때 출력이 표시되기 시작합니다.

  • 하지만당신이 보는 것은 완전한 출력이 아닙니다지금까지는 그러나마지막 10줄만 출력그 순간.

    스크립트에 20개 파일(한 번에 10개 미만, 다음 항목 참조)을 분석하도록 요청하면 스크립트가 처음 종료되기 전 마지막 10개 파일의 분석 결과만 얻을 수 있습니다.이는 스크립트 작업에 대한 기대(즉, 무결성)를 깨뜨립니다., 그 결과모든수행된 분석은 출력에 보고되어야 합니다.

  • 이 문제도 영향을 받습니다 tail -f input. 11개 이상의 파일 이름이 포함된 파일 목록을 input파이프라인 에 덤프합니다.첫 번째, 결과적으로 10개의 하위 이름만 스크립트에 도달하게 됩니다.스크립트 작업의 무결성 위반다시. 두 번째부터는 더 이상 문제가 되지 않습니다.

이야기는 아직 끝나지 않았습니다...

첫 번째 파일의 끝에 도달하면 tail -f스테이징이 계속됩니다 -f.이후에 입력 파일에 추가된 모든 항목을 출력합니다..

이 단계에서는 입력 핸들을 닫지 않습니다.inotify입력 리스너문서, 그런 다음 기다리십시오. 프로그램이 입력 파일을 쓰거나 닫을 때마다 tail입력 핸들이 다시 읽혀집니다.방금 읽은 내용을 모두 인쇄하세요.) 파일 끝 2를 만날 때까지 대기 상태로 돌아갑니다. 수동으로 종료할 때까지 헹구고 반복합니다 tail -f.

  • 여기서 한 가지 문제는 "방금 읽은 내용을 모두 인쇄하세요."또한 일반적인 출력 버퍼링이 적용됩니다.출력이 터미널이 아닌 경우.

    tail -f output출력 분기가 터미널이기 때문에 사용자 자신의 사용에는 영향을 미치지 않습니다 . tail -f input그러나 다음의 영향을 받습니다.

    • 여러 파일 이름을 대화식으로 입력하면 cat > input종료할 때까지 처리가 시작되지 않는 것을 볼 수 있습니다 cat.
    • 이는 input가끔 파일 이름을 내보내는 장기 실행 프로그램에 대한 파이프라인도 작동하지 않음을 의미합니다.

결론적으로

tail -f input내 이해에 따르면 파일 끝을 수신하지 못하도록 스크립트를 마스킹 했기 때문에 스크립트는 다음과 같을 수 있습니다.악마, 파일 이름 제공자 프로그램이 왔다 갔다 할 수 있습니다.

tail -n +1 -f그래서 내 제안은 이것을 사용하여 tail끝없이 파일 끝을 찾지 않도록 하고 마지막 10줄 문제를 제거하는 것입니다. 그런 다음 이를 사용하여 stdbuf문제가 될 수 있는 버퍼링 3,4를 제어합니다 .

stdbuf -oL tail -n +1 -f input | ../entropyCalc/entropy.py > output 2>&1

그런 다음 모니터링 측면에서 다음을 사용합니다.

tail -n +1 -f output

또는:

while true; do cat output; done

각주

  • 1 더 정확하게는 업스트림 프로그램이 파이프를 닫을 때입니다. (귀하의 경우 tail -f output스크립트가 종료될 때만 발생합니다 )
  • 2는tail -f output 스크립트를 종료하지 않는 한 절대 발생하지 않습니다.두번째시간.
  • 3 스크립트는 이미 출력 단계에서 라인 버퍼링을 수행하므로 거기에 있을 필요가 없습니다 stdbuf.
  • 4표준 오류 리디렉션은 2>&1모니터링 터미널에도 스크립트 오류가 표시되도록 보장합니다.

관련 정보