パイプラインチェーンでjqを使用すると、出力は生成されません。

パイプラインチェーンでjqを使用すると、出力は生成されません。

jq出力をリダイレクトする際の明示的なフィルタの必要性について、Web全体で議論がありました。ただし、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_subIoTを通じて発見したとおり(ここで問題を発見しました)尾を包むことです。そしてシェルスクリプトの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

これはjqHomebrewを介してインストールされた最新バージョンです。

$ 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」の詳細を見つけることができます。マニュアルページもここにあります

関連情報