Em
dd if=/dev/zero bs=1024K count=1 | nc <IP_ADDR> <PORT> -q 0 | grep copied
não há como a saída de status dd
ir para grep
. grep
está lendo a saída de nc
, não dd
. Se dd
escreveu essa saída em sua stdout, ela iria para nc
, não grep
.
Felizmente, dd
não grava essa mensagem de status em seu stdout (caso contrário, ela seria enviada para <IP_ADDR>
, que não queremos), mas ela é gravada em um fluxo separado: stderr (porque é uma mensagem de diagnóstico) , não faz parte de sua saída normal).
Para ter dd
' stderr
conectado a um canal que vai para grep
(e nc
' s stdout + stderr inalterado), você poderia fazer:
{ {
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
Assumindo que stdin / stdout / stderr do shell vá para I
, O
, E
(tudo seria o dispositivo tty aberto no modo de leitura + gravação se executado a partir de um terminal), no acima teríamos :
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
Ou para ter o stderr de dd
e o stdout + stderr de nc
ir para grep
(mas o stdout de dd ainda vai para nc):
{
dd if=/dev/zero bs=1M count=1 |
nc -q 0 <IP_ADDR> <PORT>
} 2>&1 | grep copied
Nossa tabela de atribuição de fd por comando se torna:
cmd \ fd | stdin stdout stderr
---------+--------------------
dd | I pipe1 pipe2
nc | pipe1 pipe2 pipe2
grep | pipe2 O E
Ainda outra abordagem:
{
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
Mas observe que essa saída não será muito relevante. Esse 1MiB de dados provavelmente caberá no buffer do pipe, no buffer de leitura interno do nc
e no buffer de envio do soquete, assim você não estará realmente sincronizando o throughput da rede. É provável que dd
retorne antes que o primeiro pacote de dados seja enviado pela rede (logo após a conexão TCP ter sido ativada e nc
começar a ler seu stdin). Veja iperf
para isso.
Sem iperf
, você poderia obter uma medida melhor do envio de dados se fizesse 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>