netcatを介して出力からddデータを分離し、出力を解析します。

netcatを介して出力からddデータを分離し、出力を解析します。

次のコマンドを使用して、netcatを介してdd出力をコピーしました。

$dd if=/dev/zero bs=1024K count=1 | nc <IP_ADDR> <PORT> -q 0
1+0 enregistrements lus
1+0 enregistrements écrits
1048576 bytes (1,0 MB, 1,0 MiB) copied, 0,0590934 s, 17,7 MB/s

ただし、出力を解析しようとすると何も起こりません。

$ dd if=/dev/zero bs=1024K count=1 | nc <IP_ADDR> <PORT> -q 0 | grep copied
1+0 enregistrements lus
1+0 enregistrements écrits
1048576 bytes (1,0 MB, 1,0 MiB) copied, 0,058937 s, 17,8 MB/s

最後の行だけを印刷する必要がありますが、出力がgrepに送信されないのはなぜですか?何度もリダイレクトしようとしましたが、好きなように機能しませんでした。

netcatを介してデータを送信したいのですが、後で解析するために出力メッセージ(stderrとstdin)をstdoutまたはファイルに送信したいと思います。

答え1

存在する

dd if=/dev/zero bs=1024K count=1 | nc <IP_ADDR> <PORT> -q 0 | grep copied

代わりに、ステータス出力が読み取っている.outputddに移動することはできません。その出力が標準出力に書き込まれると、代わりに移動されます。grepgrepncddddncgrep

ありがたいことddに、そのステータスメッセージを標準出力に書き込むのではなく(そうでなければ<IP_ADDR>私たちが望んでいない場所に送信します)、代わりに別のストリームであるstderrに書き込みます(これは診断メッセージの一部ではなく診断メッセージであるため)。通常の出力)。

(およびのstdout + stderrは変更されていません)で接続されているパイプにdd'を接続するには、次のようにします。stderrgrepnc

{ {
  dd if=/dev/zero bs=1M count=1 2>&3 3>&- |
    nc -q 0  <IP_ADDR> <PORT> 3>&-
} 3>&1 >&4 4>&- | grep copied 4>&-; } 4>&1

シェルの stdin/stdout/stderr がI, O, E(ターミナルで実行される場合すべて tty デバイスを読み書きモードで開きます) で行くと仮定すると上記の結果は次のとおりです。

cmd \ fd | stdin stdout stderr  3       4
---------+------------------------------------
      dd | I     pipe1  pipe2   closed  closed
      nc | pipe1 O      E       closed  closed
    grep | pipe2 O      E       closed  closed

またはstderrddとstdout + stderrをncそのまま使用しますgrep(ただし、ddのstdoutはまだncに移動します)。

{ 
  dd if=/dev/zero bs=1M count=1 |
    nc -q 0  <IP_ADDR> <PORT>
} 2>&1 | grep copied

各コマンドのfd割り当てテーブルは次のとおりです。

cmd \ fd | stdin stdout stderr
---------+--------------------
      dd | I     pipe1  pipe2
      nc | pipe1 pipe2  pipe2
    grep | pipe2 O      E

別の方法があります:

{ 
  dd if=/dev/zero bs=1M count=1 2>&1 >&3 3>&- |
    grep copied >&2 3>&-
} 3>&1 | nc -q 0  <IP_ADDR> <PORT>

cmd \ fd | stdin stdout stderr  3
---------+-----------------------
      dd | I     pipe1  pipe2
      nc | pipe1 O      E
    grep | pipe2 E      E

ただし、この出力はあまり関連性がありません。この1MiBのデータは、パイプバッファ、nc内部読み取りバッファ、およびソケット転送バッファに適している可能性があるため、実際にはネットワークスループットを測定しません。dd最初のパケットがネットワーク経由で送信される前に返される可能性が高くなります(ncTCP接続がアクティブになり、標準入力の読み取りを開始した直後)。iperf反対側を見てください。

そうでない場合は、iperf次のようにして転送スループットをよりよく測定できます。

{
  dd bs=1M count=50 2> /dev/null # buffers filled and the TCP connection 
                                 # established and into a steady state
  dd bs=1M count=100 2>&1 >&3 3>&- | grep copied >&2 3>&-
} < /dev/zero 3>&1 | nc -q 0  <IP_ADDR> <PORT>

関連情報