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).