一致を見つけた後、Grepの終了が遅いですか?


20

デバイス接続のbtmonをポーリングするbashスクリプトを作成しようとしています。私は実用的なソリューションを持っていますが、それはばかげて遅いです、そして、問題はgrepがマッチを見つけた後に終了するのが非常に遅いようです(約25秒)。高速化grepするか、まったく使用しないようにするにはどうすればよいですか?

#!/bin/bash
COUNTER=0
while :
  do
    until btmon | grep -m 1 '@ Device Connected'
      do :
    done
    let COUNTER=COUNTER+1
    echo on 0 | cec-client RPI -s -d 1
    sleep 5
    echo as | cec-client RPI -s -d 1
    until btmon | grep -m 1 '@ Device Disconnected'
      do :
    done
    let COUNTER=COUNTER-1
    if [ $COUNTER -eq 0 ];
      then echo standby 0 | cec-client RPI -s -d 1;
    fi
done

編集:明確にするためbtmonに、Bluezスイートの一部であるbluetooth監視ツールであり、cec-clientは(特に)HDMI-CECシリアルバスを介してコマンドを発行するためのlibCECにパッケージ化されたユーティリティです。


2
どのくらいの「もの」がbtmon出力されますか?バッファリングだけの問題ではないのですか?
スチールドライバー

@steeldriver出向 パイプのバッファリング無効にしようとましたか?
l0b0

btmonは毎秒約250文字を出力します。
ロブ

@ l0b0 unbufferコマンドを使用してバッファリングを無効にしようとしましたが、grepがまったく終了しないようです。また、grepを--line-bufferモードに強制しようとしましたが、それは役に立たなかったようです。
ロブ

btmonバッファリング自体を実装している可能性がありますが、その場合は運が悪いです。
-l0b0

回答:


28

に:

cmd1 | cmd2

ほとんどのシェル(Bourneシェル、(t)csh、およびyashといくつかのバージョンのAT&T kshは、いくつかの例外が顕著な例外である)は、cmd1との両方を待ちcmd2ます。

bash、あなたはそれに気づくでしょう

sleep 1 | uname

1秒後に戻ります。

に:

btmon | grep -m 1 '@ Device Disconnected'

grepパターンの1つのオカレンスを検出するとすぐに終了しますが、bashまだ待機しbtmonます。

btmon通常grep、返された後にパイプに次に書き込むときにSIGPIPEで終了しますが、再度何も書き込まない場合、そのシグナルを受信することはありません。

あなたは置き換えることができ#! /bin/bash#! /bin/ksh93いると互換性の殻だとしてbashだけでパイプラインの最後のコンポーネントを待ち、1。それから

btmon | grep -m 1 '@ Device Disconnected'

後にgrep戻ると、btmonバックグラウンドで実行されているままにしてしまうと、シェルはスクリプトの残りの部分とに運ぶだろう。

POSIXlyに戻るbtmonとすぐに殺したい場合grepは、次のようなことができます。

sh -c 'echo "$$"; exec btmon' | (
   read pid
   grep -m1 '@ Device Disconnected' || exit
   kill "$pid" 2> /dev/null
   true)

3
これがそのように振る舞う理由を説明してくれてありがとう。bashがbtmonの終了を待っている可能性は私にはありませんでした。ksh93へのスワッピングは美しく機能します!
ロブ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.