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
IoT를 통해 발견한 대로(여기서 문제를 발견했습니다) 꼬리를 감싸는 것입니다.그리고쉘 스크립트의 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
이것은 파이프라인 체인을 이해하는 데 있어 (대체로 문서화되지 않은) 오류입니까?
답변1
jq
표준 출력이 터미널이 아닌 경우 해당 출력은 버퍼링됩니다.
jq
각 객체의 출력 버퍼가 이후에 플러시되도록 요청하려면 --unbuffered
해당 옵션을 사용하세요.
tail -f in.txt | jq --unbuffered '.f1' | tee out.txt
jq
매뉴얼 에서 :
--unbuffered
각 JSON 개체를 인쇄한 후 출력을 플러시합니다( 느린 데이터 소스를 다른 곳으로 파이프
jq
하고 출력을 파이프 하는 경우jq
유용함 ).
답변2
여기서 볼 수 있는 것은 C stdio 버퍼링이 작동하는 모습입니다. 특정 제한(512바이트, 4KB 이상)에 도달할 때까지 출력을 버퍼에 저장한 다음 모든 출력을 한 번에 보냅니다.
stdout이 터미널에 연결되면 이 버퍼링은 자동으로 비활성화되지만 파이프에 연결되면(귀하의 경우처럼) 이 버퍼링 동작이 활성화됩니다.
버퍼링을 비활성화/제어하는 일반적인 방법은 이 setvbuf()
기능을 사용하는 것입니다(참조:이 답변자세한 내용은) 그러나 이 작업은 jq
소스 코드 자체에서 수행되어야 하므로 실용적이지 않을 수 있습니다...
해결 방법이 있습니다... (누군가는 해킹이라고 말할 수도 있습니다.) "expect"와 함께 배포되는 "unbuffer"라는 프로그램이 있는데, 이 프로그램은 의사 터미널을 생성하고 이를 프로그램에 연결합니다. 따라서 jq
파이프에 계속 쓰고 있더라도 터미널에 쓰고 있다고 생각하여 버퍼링 효과가 비활성화됩니다.
아직 없는 경우 "unbuffer"와 함께 제공되는 "expect" 패키지를 설치합니다. 예를 들어 Debian(또는 Ubuntu)의 경우:
$ sudo apt-get install expect
그런 다음 다음 명령을 사용할 수 있습니다.
$ tail -f in.txt | unbuffer -p jq '.f1' | tee out.txt
당신은 또한 볼 수 있습니다이 답변"unbuffer"에 대한 자세한 내용을 찾을 수 있습니다.매뉴얼 페이지도 여기에 있습니다.