가장 쉬운 방법은 비 블로킹 출력을 설정하는 일부 프로그램을 통해 파이프하는 것입니다. 다음은 간단한 perl oneliner입니다 (leakybuffer로 저장할 수 있음 ).
그래서 당신 a | b
은됩니다 :
a | perl -MFcntl -e \
'fcntl STDOUT,F_SETFL,O_NONBLOCK; while (<STDIN>) { print }' | b
무엇인가는 입력을 읽고 출력에 쓰기 (와 동일 cat(1)
)이지만 출력은 비 블로킹입니다. 즉, 쓰기에 실패하면 오류를 반환하고 데이터를 잃을 것이지만 프로세스는 다음 입력 줄을 계속 진행합니다. 오류. 프로세스는 원하는대로 일종의 라인 버퍼링되지만 아래의주의 사항을 참조하십시오.
예를 들어 다음과 같이 테스트 할 수 있습니다.
seq 1 500000 | perl -w -MFcntl -e \
'fcntl STDOUT,F_SETFL,O_NONBLOCK; while (<STDIN>) { print }' | \
while read a; do echo $a; done > output
다음 output
과 같이 잃어버린 줄을 가진 파일을 얻을 것입니다 (정확한 출력은 쉘의 속도 등에 달려 있습니다).
12768
12769
12770
12771
12772
12773
127775610
75611
75612
75613
당신은 쉘 후 라인을 잃은 어디에 있는지 12773
펄이 충분한 버퍼를 가지고 있지 않았다 -하지만, 또한이 이상 12774\n
하지만 위해 한 1277
그래서 다음 번호가 - 그냥 쓴 있도록 75610
라인의 시작 부분에 시작되지 않는 작은 그것을 만들기 추한.
쓰기가 성공적으로 완료되지 않은 경우 펄을 감지하여 나중에 개선 될 수있다가 나중에 새 라인이 나오는 것을 무시하고 나머지 라인을 플러시하려고 시도하지만 펄 스크립트를 훨씬 더 복잡하게 만들 수 있으므로 관심있는 독자 :)
업데이트 (이진 파일의
경우 ) : 줄 바꾸기로 끝나는 줄 (로그 파일 등)을 처리하지 않는 경우 명령을 약간 변경해야합니다. 그렇지 않으면 펄이 입력에 줄 바꿈 문자가 나타나는 빈도에 따라 많은 양의 메모리를 소비합니다.
perl -w -MFcntl -e 'fcntl STDOUT,F_SETFL,O_NONBLOCK; while (read STDIN, $_, 4096) { print }'
이진 파일에서도 추가 메모리를 사용하지 않고도 올바르게 작동합니다.
업데이트 2-더 나은 텍스트 파일 출력 :
출력 버퍼 피하기 ( syswrite
대신 print
) :
seq 1 500000 | perl -w -MFcntl -e \
'fcntl STDOUT,F_SETFL,O_NONBLOCK; while (<STDIN>) { syswrite STDOUT,$_ }' | \
while read a; do echo $a; done > output
나를 위해 "병합 된 라인"문제를 해결하는 것 같습니다 :
12766
12767
12768
16384
16385
16386
(참고 : perl -ne '$c++; next if $c==$_; print "$c $_"; $c=$_' output
oneliner 로 어떤 라인 출력이 절단되었는지 확인할 수 있습니다 )