Separe los datos dd de la salida a través de netcat para analizar la salida

Estoy copyndo salida dd a través de netcat con el siguiente command

$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 

Sin embargo, cuando trato de analizar la salida, no pasa nada

 $ 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 

Debería imprimir solo la última línea, ¿por qué la salida no se envía a grep? Intenté algunas networkingirecciones, pero no puedo networkingirigirlas como quiero.

Me gustaría que los datos se envíen a través de netcat, pero que los posts de salida (tanto stderr como stdin) se envíen a stdout o un file para analizarlos posteriormente.

En

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

no hay forma de que la salida de estado dd pueda pasar a grep . grep está leyendo la salida de nc , no dd . Si dd escribiera esa salida en su stdout, iría a nc , no grep .

Afortunadamente dd no escribe ese post de estado en su stdout (de lo contrario, sería enviado a <IP_ADDR> que no queremos), pero lo escribe en una secuencia separada: stderr (ya que es un post de diagnóstico, no parte de su salida normal).

Para tener dd 's stderr conectado a una tubería que va a grep (y nc 's stdout + stderr sin cambios), podría hacer:

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

Suponiendo que el shell stdin / stdout / stderr vaya a I , O , E (todo sería el dispositivo tty abierto en modo lectura + escritura si se ejecuta desde un terminal), en el ejemplo anterior tendríamos:

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

O para que stderr de dd y stdout + stderr de nc pasen a grep (pero el stdout de dd sigue yendo a nc):

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

Nuestra tabla de asignación fd por command se convierte en:

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

Sin embargo, otro enfoque:

 { 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 OE grep | pipe2 EE 

Pero tenga en count que ese resultado no será muy relevante. Es probable que esos 1Mib de datos encajen en el buffer de la tubería, el buffer interno de lectura de nc y el buffer de envío del socket, por lo que no estará realmente midiendo el performance de la networking. Es probable que dd vuelva antes de que se envíe el primer package de datos a través de la networking (poco después de que la connection TCP se haya habilitado y nc comience a leer su código fuente). Mira a iperf cambio por eso.

Sin iperf , podría get una mejor medición del performance de envío si hiciera algo como:

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