次のコマンドを使用して、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
に移動することはできません。その出力が標準出力に書き込まれると、代わりに移動されます。grep
grep
nc
dd
dd
nc
grep
ありがたいことdd
に、そのステータスメッセージを標準出力に書き込むのではなく(そうでなければ<IP_ADDR>
私たちが望んでいない場所に送信します)、代わりに別のストリームであるstderrに書き込みます(これは診断メッセージの一部ではなく診断メッセージであるため)。通常の出力)。
(およびのstdout + stderrは変更されていません)で接続されているパイプにdd
'を接続するには、次のようにします。stderr
grep
nc
{ {
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
最初のパケットがネットワーク経由で送信される前に返される可能性が高くなります(nc
TCP接続がアクティブになり、標準入力の読み取りを開始した直後)。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>