Eu quero usar o netcat como um servidor TCP que lê dados de um pipe nomeado. Para isso fiz o seguinte:
Etapa 1. Criei um canal e o servidor que o usa como origem
mkfifo /tmp/all.pipe
nc -k -l 8080 < /tmp/all.pipe
Passo 2. Criei um cliente que lê os dados continuamente:
while true; do
sleep 1;
echo "Check connection";
while IFS= read -r line; do
printf "$line";
done < /dev/tcp/localhost/8080;
done
Etapa 3. Gravar alguns dados no pipe:
echo "hello" > /tmp/all.pipe
Após a execução dessas 3 etapas, a saída no lado do cliente foi:
...
bash: connect: Connection refused
bash: /dev/tcp/localhost/8080: Connection refused
Check connection
bash: connect: Connection refused
bash: /dev/tcp/localhost/8080: Connection refused
Check connection
hello
No entanto, quando executei a etapa 3 novamente, a saída não mudou. Parece que aconteceu porque a conexão ainda estava ativa, mas os novos dados não foram passados do pipe para o nc e depois para o cliente. Por que? O que pode ser feito para alcançá-lo?
Sobre:
O shell tenta abrir
/tmp/all.pipe
e trava, pois ainda não há nenhum processo que tenha aberto o canal nomeado para gravação.Como
nc
ainda não foi iniciado, isso explica por quebash
uma conexão é recusada ao tentar se conectar lá.Quando você faz
Então é quando o primeiro comando é desbloqueado. O pipe agora está instanciado.
Em seguida,
echo
escrevehello\n
lá e termina, no ponto em que a extremidade de gravação do pipe é fechada enc
verá o fim do arquivo em seu stdin. Se você tivesse usadocat
em vez denc
,cat
teria terminado.Mas para
nc
, seu stdout ainda vai para o terminal naquele ponto e a conexão TCP ainda está ativa, portanto, mesmo que haja uma extremidade que atingiu o fim da entrada, ela continua. Sebash
enviasse algo nesse soquete, isso seria exibido nonc
stdout de 's, por exemplo.Quando você faz um segundo
echo something > /tmp/all.pipe
, comonc
não fechou seu fd no pipe (pelo menos é o caso do donc
pacotenetcat-openbsd
no Ubuntu, YMMV), ele passa por esse mesmo pipe que vai ao ar novamente, masnc
já desistiu de ler desde que tinha atingido eof anteriormente.O mais fácil aqui é provavelmente abrir o canal para
nc
a entrada de no modo de leitura + gravação, para que seja instanciado imediatamente e sempre viva tanto quantonc
vidas.Para isso, basta substituir
<
por<>
nanc
linha de comando:Observe também que o primeiro argumento
printf
é o formato, você não deve ter nenhuma variável lá. Se você quiser imprimir a linha de entrada sem o delimitador de linha, use: