![파이프에서 읽을 때 awk가 완전히 버퍼링되는 이유는 무엇입니까?](https://linux55.com/image/21459/%ED%8C%8C%EC%9D%B4%ED%94%84%EC%97%90%EC%84%9C%20%EC%9D%BD%EC%9D%84%20%EB%95%8C%20awk%EA%B0%80%20%EC%99%84%EC%A0%84%ED%9E%88%20%EB%B2%84%ED%8D%BC%EB%A7%81%EB%90%98%EB%8A%94%20%EC%9D%B4%EC%9C%A0%EB%8A%94%20%EB%AC%B4%EC%97%87%EC%9E%85%EB%8B%88%EA%B9%8C%3F.png)
nmea 문자열을 보내는 GPS 장치에 연결된 직렬 포트에서 데이터를 읽고 있습니다.
내 요점을 설명하기 위한 간단한 호출은 다음과 같습니다.
$ awk '{ print $0 }' /dev/ttyPSC9
GPGGA,073651.000,6310.1043,N,01436.1539,E,1,07,1.0,340.2,M,33.3,M,,0000*56
$GPGSA,A,3,28,22,09,27,01,19,17,,,,,,2.3,1.0,2.0*39
$GPRMC,073651.000,A,6310.1043,N,01436.1539,E,0.42,163.42,070312,,,A*67
GPGGA,073652.000,6310.1043,N,01436.1540,E,1,07,1.0,339.2,M,33.3,M,,0000*55
$GPGSA,A,3,28,22,09,27,01,19,17,,,,,,2.3,1.0,2.0*39
파이프에서 읽으려고 하면 awk는 입력을 stdout으로 보내기 전에 버퍼링합니다.
$ cat /dev/ttyPSC9 | awk '{ print $0 }'
<long pause>
GPGGA,073651.000,6310.1043,N,01436.1539,E,1,07,1.0,340.2,M,33.3,M,,0000*56
$GPGSA,A,3,28,22,09,27,01,19,17,,,,,,2.3,1.0,2.0*39
$GPRMC,073651.000,A,6310.1043,N,01436.1539,E,0.42,163.42,070312,,,A*67
GPGGA,073652.000,6310.1043,N,01436.1540,E,1,07,1.0,339.2,M,33.3,M,,0000*55
$GPGSA,A,3,28,22,09,27,01,19,17,,,,,,2.3,1.0,2.0*39
버퍼링을 방지하는 방법은 무엇입니까?
편집하다:Kyle Jones는 cat이 출력을 버퍼링하고 있다고 제안했지만 이런 일은 일어나지 않는 것 같습니다.
$ strace cat /dev/ttyPSC9 | awk '{ print $0 }'
write(1, "2,"..., 2) = 2
read(3, "E"..., 4096) = 1
write(1, "E"..., 1) = 1
read(3, ",0"..., 4096) = 2
생각해 보면 프로그램은 터미널에 쓸 때 라인 버퍼링을 사용하고 다른 모든 경우에는 "일반 버퍼링"을 사용하는 것 같습니다. 그렇다면 고양이는 왜 더 많은 버퍼링을 수행하지 않습니까? 직렬 포트 신호가 EOF입니까? 그렇다면 고양이는 왜 종료되지 않습니까?
내 awk
것은 mawk 1.2입니다.
답변1
나는 이것이 오래된 질문이라는 것을 알고 있지만, 여기에서 그것을 찾는 사람들에게 다음 문장이 도움이 될 수 있습니다.
cat /dev/ttyPSC9 | awk '{ print $0; system("")}'
system("")
작동하며 POSIX와 호환됩니다. Non-posix 시스템: 주의하세요.
동일한 작업을 수행하는 보다 구체적인 함수가 존재 fflush()
하지만 이전 버전의 awk에서는 사용할 수 없습니다.
중요한 메시지가 옵니다.문서사용 정보 system("")
:
gawk는 system() 함수의 이러한 사용을 특별한 경우로 처리하고 빈 명령으로 쉘(또는 다른 명령 해석기)을 실행하지 않을 만큼 똑똑합니다. 그러므로 gawk에게 이 관용구는 유용할 뿐만 아니라 효율적이기도 합니다.
답변2
아마도 cat이 아닌 awk로 버퍼링되어 있을 것입니다. 첫 번째 경우 awk는 입력과 출력이 TTY이기 때문에 대화형이라고 생각합니다(비록 서로 다른 TTY임에도 불구하고 - awk는 이를 확인하지 않는 것 같습니다). 두 번째 항목에서는 입력이 파이프이므로 비대화형으로 실행됩니다.
awk 프로그램에서 명시적으로 새로 고쳐야 합니다. 하지만 휴대성이 없습니다.
출력을 새로 고치는 방법에 대한 자세한 배경 및 세부 정보는 다음을 참조하세요.http://www.gnu.org/software/gawk/manual/html_node/I_002fO-Functions.html
답변3
오래된 주제이지만 마법을 사용하지 않고도 투명한 방식으로 스트림 버퍼링 동작을 변경하는 솔루션을 추가할 가치가 있습니다 system("")
. :-)
cat /dev/ttyPSC9 | stdbuf --output=L awk '{print $0}'
저는 최근에 D-Bus 이벤트를 캡처하는 데 직접 사용했습니다.
gdbus monitor -y -d org.freedesktop.login1 | stdbuf -oL grep LockedHint