timeout command e pipe - ordem de precedência

0

Eu preciso testar o recebimento de dados TCP. Eu não posso usar iperf.

Os requisitos estão dizendo que eu deveria criar um servidor TCP para o qual alguém enviará dados aleatórios. Eu preciso contar o número de bytes recebidos.

Foi-me dito para usar o seguinte:

timeout 60 cat < /dev/tcp/IP_addr/port | wc –c > byte_count-n.txt

Isso fará o que eles acham que será? Será que ele receberá dados por 60 segundos e, quando o tempo limite expirar, enviará os dados recebidos para wc , que gravará o total em um arquivo de disco?

Como programador, eu me sentiria mais feliz se lesse

(timeout 60 cat < /dev/tcp/IP_addr/port) | wc –c > byte_count-n.txt

Mas obviamente a concha não aceita isso. Estou certo em estar preocupado?

Note que estamos usando o shell Ash, mas há alguma preocupação de que apenas o Bash suporte /dev/tcp

    
por Mawg 19.12.2016 / 10:45

1 resposta

2

Note que isto responde a uma versão anterior da questão onde o comando deveria ser um servidor .

Não, em bash (e ksh de onde esse recurso vem), /dev/tcp/host/port são arquivos virtuais destinados a conexões TCP cliente .

O shell irá conectar ao host: port, e fará com que o socket conectado seja o fd que é o assunto do redirecionamento. Com < ou <> , é fd 0 (stdin), com > , >> é fd 1, mas os operadores não fazem diferença. Em particular, não é porque você usa < que o shell desliga a direção de envio do socket; O stdin ainda estará conectado a um soquete que você pode ler e gravar.

Se você quiser ouvir (ser um servidor) e aceitar uma ou mais conexões, não será possível usar /dev/tcp/host/port .

Você precisaria usar uma ferramenta dedicada, como socat ou nc , ou um shell com suporte interno para o mesmo zsh com seu ztcp incorporado.

timeout 60 socat -u tcp-listen:12345,reuseaddr,bind=127.0.0.1,fork - | wc -c

Ouvirão na porta 12345 no endereço IPv4 de loopback e aceitarão conexões de entrada em processos filhos, escreverão o que é recebido no stdout (aqui canalizado para wc ).

Existem várias implementações de uma ferramenta chamada nc ou netcat com as quais você geralmente pode fazer o mesmo com:

timeout 60 nc -l 127.0.0.1 12345 | wc -c

Observe que ele executa esse comando por 60 segundos. Isso inclui o tempo enquanto ele está sentado sem fazer nada esperando por conexões de entrada.

Se você quiser que o timer inicie na conexão de entrada, você pode fazer isso:

socat -u tcp-listen:12345,reuseaddr,bind=127.0.0.1 'EXEC:timeout 60 cat' | wc -c

Aqui aceitando apenas uma conexão TCP (sem fork ), que é canalizada para timeout 60 cat .

Só para esclarecer o que acho que você pode estar perguntando no assunto, quando fizer:

 cmd1 | cmd2

Não é cmd1 em execução e, quando terminar, os dados são enviados para cmd2 . Em vez disso, cmd1 e cmd2 são iniciados simultaneamente (eles são executados em paralelo) com um canal entre eles (% de stdout decmd1 é a extremidade de gravação do canal e o stdin de cmd2 é o final da leitura).

Em:

 timeout 60 nc -l 127.0.0.1 12345 | wc -c

Você tem timeout e wc em execução em paralelo. timeout inicia outro processo no qual ele executa nc (que compartilhará o mesmo stdout).

Após 60 segundos, timeout irá matar esse outro processo. Nesse momento, nc sairá, mas terá escrito o que recebeu do socket para o pipe ( nc ou socat não armazena em buffer sua saída), portanto, mesmo se wc não leu ainda assim, será contabilizado como wc continuará lendo até que o tubo esteja vazio.

(timeout 60 nc ...) | wc –c

Seria o mesmo. (code) é iniciar um subshell (um processo de shell filho (em shells que não o ksh93) que está avaliando o code ). Mas aqui, já que é parte do pipeline, esse código deve estar em uma sub-linha já (partes diferentes de um pipeline devem ser executadas em processos diferentes enquanto são executados simultaneamente).

    
por 19.12.2016 / 11:02

Tags