저는 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
모니터링 터미널에도 스크립트 오류가 표시되도록 보장합니다.