複数のパイプによるping出力のフィルタリングが失敗します。

複数のパイプによるping出力のフィルタリングが失敗します。

ping出力からパケットの戻り時間だけをキャプチャしようとすると、次の問題が発生します。

$ ping 192.168.0.1 | grep -o '[^ =]* ms'

各パケットの到着時間を表示することで動作します。時間単位も削除したいので、これで十分だろうと思いました。

$ ping 192.168.0.1 | grep -o '[^ =]* ms' | grep -o '^[^ ]*'

しかし、驚くべきことに、出力は表示されずに中断されます。ただし、echo最初のコマンドを出力のサンプル行に置き換えると、期待pingどおりに動作します(出力5.07)。

$ echo '64 bytes from 192.168.0.1: icmp_seq=10 ttl=64 time=5.07 ms' | grep -o '[^ =]* ms' | grep -o '^[^ ]*'

ミリ秒単位で時間を取得する別の方法を見つけましたが、まだpingコマンドに何が問題ですか? 1つのパイプを通っては大丈夫ですが、2つのパイプを通っては大丈夫ではありません。

PS:以下のバージョンも失敗しますが、そのechoバージョンは成功するため、問題は発生しません。grep

$ ping 192.168.0.1 | grep -o '[^ =]* ms' | sed 's_ ms__'
$ ping 192.168.0.1 | grep -o '[^ =]* ms' | cut -f 1 -d ' '
$ ping 192.168.0.1 | cut -f 7 -d ' ' | cut -f 2 -d '='

答え1

確かな答えはラインバッファping -c 3を使用する代わりに、ping最初のコマンドが完了したときにのみすべての出力が生成されることを使用してこれを実証できます。

GNUの回避策として、grep2つのフィルタを1つに減らすことができます

ping 192.168.0.1 | grep -oP '[[:digit:].]+(?= ms)'

あるいは、本当に両方のフィルタを使用したい場合は、grep --line-buffered ...どちらかstdbuf -oL grep ...が適切です。

答え2

あなたの問題はシェルのラインバッファリングによって引き起こされたようです。

コマンドを十分に長時間実行すると、いくつかの出力が表示されます。
または、次のようにping数を制限します。

$ ping -c4 192.168.0.1 | grep -o '[^ =]* ms' | grep -o '^[^ ]*'

これによれば、より多くの情報と解決策(ソリューション?)があります。協会

関連情報