jq
출력이 리디렉션 될 때 명시 적 필터 가 필요한 문제 는 웹 전체에서 논의됩니다. 그러나 jq
명시 적 필터를 사용하는 경우에도 파이프 체인의 일부인 경우 출력을 리디렉션 할 수 없습니다 .
치다:
touch in.txt
tail -f in.txt | jq '.f1'
# in a different terminal:
echo '{"f1":1,"f2":2}' >> in.txt
echo '{"f1":3,"f2":2}' >> in.txt
예상 한대로 jq
명령 의 원래 터미널 출력 은 다음과 같습니다.
1
3
그러나 jq
명령 끝에 리디렉션 또는 파이핑을 추가 하면 출력이 자동으로 진행됩니다.
rm in.txt
touch in.txt
tail -f in.txt | jq '.f1' | tee out.txt
# in a different terminal:
echo '{"f1":1,"f2":2}' >> in.txt
echo '{"f1":3,"f2":2}' >> in.txt
첫 번째 터미널에 출력이 나타나지 않고 out.txt가 비어 있습니다.
수백 가지 변형을 시도했지만 찾기 어려운 문제입니다. 은 내가 찾은 해결 을 통해 발견으로, mosquitto_sub
그리고 (나는 또한 문제가 발견 된 곳이었다)없는 것들 네트워크, 꼬리 래핑하는 것입니다 및 쉘 스크립트에서 JQ 기능 :
#!/bin/bash
tail -f $1 | while IFS='' read line; do
echo $line | jq '.f1'
done
그때:
./tail_and_jq.sh | tee out.txt
# in a different terminal:
echo '{"f1":1,"f2":2}' >> in.txt
echo '{"f1":3,"f2":2}' >> in.txt
그리고 충분히 출력이 나타납니다.
1
3
jq
Homebrew를 통해 최신 버전으로 설치되어 있습니다.
$ echo $SHELL
/bin/bash
$ jq --version
jq-1.5
$ brew install jq
Warning: jq 1.5_3 is already installed and up-to-date
이것은 jq
파이프 체인에 대한 이해와 관련 이 있거나 (문서화되지 않은) 버그 입니까?
답변
로부터의 출력은 jq
표준 출력이 파이프 때 버퍼링된다.
jq
모든 객체 후에 출력 버퍼 를 플러시하도록 요청하려면 --unbuffered
옵션을 사용하십시오.
tail -f in.txt | jq --unbuffered '.f1' | tee out.txt
로부터 jq
수동 :
--unbuffered
각 JSON 객체가 인쇄 된 후 출력을 플러시합니다 (느린 데이터 소스를
jq
파이핑하고jq
다른 곳의 출력을 파이핑하는 경우 유용 ).
답변
여기서보고있는 것은 C stdio 버퍼링 작동입니다. 특정 한계 (512 바이트 또는 4KB 이상)에 도달 할 때까지 출력을 버퍼에 저장 한 다음 한 번에 전송합니다.
이 버퍼링은 stdout이 터미널에 연결된 경우 자동으로 비활성화되지만 파이프와 같은 경우 (예 : 경우와 같이)이 버퍼링 동작을 활성화합니다.
버퍼링을 비활성화 / 제어하는 일반적인 방법은 setvbuf()
기능을 사용하는 것입니다 ( 자세한 내용 은 이 답변 참조). 소스 코드 jq
자체 에서 수행해야 하므로 실제적이지 않을 수도 있습니다 …
해결 방법이 있습니다 … (해킹, 아마도 말할 수 있습니다.) “언 버퍼”라는 프로그램이 있습니다. “버퍼”는 의사 터미널을 만들고 프로그램에 연결할 수있는 “expect”로 배포됩니다. 따라서 jq
파이프에 계속 쓰 더라도 터미널에 쓰고 있다고 생각하고 버퍼링 효과가 비활성화됩니다.
“expect”패키지를 설치하십시오. 만약 “unbuffer”가 없다면, 데비안 (또는 우분투)에 설치하십시오 :
$ sudo apt-get install expect
그런 다음이 명령을 사용할 수 있습니다.
$ tail -f in.txt | unbuffer -p jq '.f1' | tee out.txt
“언 버퍼”에 대한 자세한 내용은 이 답변 을 참조하십시오 . 맨 페이지도 여기에서 찾을 수 있습니다 .