Qual a diferença entre esses quatro comandos (fifo, substituição de processo, redirecionamento ...)

8

Meu objetivo é criar um servidor de eco simples nce um único fifo. Não estou procurando a melhor maneira de fazer isso, estou apenas tentando entender a semântica dos seguintes comandos (quando o fork acontece, por que, o que muda, por que os comandos se comportam de maneira diferente ...).

Estou usando Bash, então eu não tenho certeza se todos os comandos irá funcionar com um POSIX shou zsh, ksh...

Aqui estão os quatro comandos que estou mencionando no título (supondo que já o fiz mkfifo fifo):

cat fifo | nc -l localhost 8888 > fifo
exec 3<> fifo && nc -l localhost 8888 <&3 >&3 && exec 3>&-
nc -l localhost 8888 <(cat fifo) > fifo
nc -l localhost 8888 < fifo > fifo

Agora eu esperaria que os 4 comandos fizessem a mesma coisa, no mínimo os dois últimos fizessem a mesma coisa.

  1. O primeiro comando se comporta conforme o esperado, um servidor de eco simples que é desligado quando o cliente fecha a conexão.
  2. Comporta-se como 1.
  3. Posso me conectar ao servidor, enviar dados, mas nunca recebo nada de volta. Quando fecho a conexão do cliente, o servidor é encerrado.
  4. Não é possível conectar-se ao servidor, o servidor escuta para sempre.
foo
fonte

Respostas:

8

A chave aqui é que abrir um FIFO é uma operação de bloqueio. O openúnico retorno é quando as duas extremidades estiverem conectadas, ou seja, quando o fifo estiver aberto para leitura e escrita.

homem fifo (7)

Normally, opening the FIFO blocks until the other end is opened also.

No 1º caso, o shell bifurca-se para executar o pipeline, abrindo o fifo para leitura ( cat fifo) e abrindo o fifo para escrita ( > fifo) acontecem em processos separados, assim acontecem independentemente.

No segundo caso, o aberto para leitura e aberto para escrita ( 3<>fifo) acontece em uma única etapa.

No terceiro caso, <(cat fifo)expande para um nome de arquivo, por exemplo /dev/fd/42. Então é como se você estivesse correndo nc -l localhost 8888 /dev/fd/42 > fifo. Você precisa de um extra <para ser equivalente, por exemplo nc -l localhost 8888 < <(cat fifo) > fifo.

No quarto caso, o shell está tentando abrir o fifo para leitura ( < fifo) e para escrever ( > fifo) como parte do mesmo processo. O shell faz um de cada vez, da esquerda para a direita. Por isso, tenta abrir fifopara leitura e bloqueia para sempre, esperando que algo se abra fifopara escrever. Acho que você descobrirá que, nesse caso, ncnem sequer começou, e a porta nunca foi aberta para ouvir.

Mikel
fonte
Ah, sim, erro bobo no # 3, mas no final o resultado permanece o mesmo. Apenas outra questão que é mais curiosa do que qualquer outra coisa, é o executivo a única maneira de abrir o fifo para r / w em uma única etapa? E existe outra maneira de forçar o casco a bifurcar-se como no nº 1? Obrigado!
foo
nc ... <>fifodeve ser suficiente. gnu.org/software/bash/manual/html_node/Redirections.html
Mikel
1
O shell será bifurcado sempre que você usar um pipeline, subshell ou substituição de processo.
Mikel
2
Correção, você precisará nc ... <>fifo >&0, já que <>fifoabre fifopara leitura e gravação em fd 0, e queremos que a saída também vá para lá.
Mikel