通过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

状态输出不可能dd转到grep.grep正在读取 的输出nc,而不是dd。如果dd将该输出写入其标准输出,它将转到nc,而不是grep

值得庆幸的是,dd它不会将该状态消息写入其标准输出(否则它将被发送到<IP_ADDR>我们不想要的地方),而是将其写入一个单独的流:stderr(因为它是诊断消息,而不是其正常输出的一部分)。

要将 dd'stderr连接到一个通往grep(并且nc's stdout+stderr 不变)的管道,您可以这样做:

{ {
  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

假设 shell 的 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+stderrnc转到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会在第一个数据包通过网络发送之前返回(在启用 TCP 连接并nc开始读取其标准输入后不久)。看看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>

相关内容