Como ler de um pipe nomeado depois que o processo do gravador sai?

2

Eu quero usar pipes nomeados como filas de tarefas assíncronas (talvez do tipo JMS).

Por exemplo, suponha que um cliente envie alguns dados que desejo inserir em um banco de dados, mas quero que o cliente desconecte-se do servidor imediatamente e o processo do servidor canalize os dados para um canal nomeado. Em seguida, leia de forma completamente independente os dados do pipe e execute uma inserção SQL, que pode ser muito lenta - mas o cliente não percebe porque obtém uma resposta imediatamente.

Como protótipo, achei que isso funcionaria (para simplificar, o "45" é ecoado em vez de ser enviado por um par de cliente-servidor netcat):

zsh> nohup echo "45" > my_named_pipe &
zsh> exit
zsh: warning: 1 jobs SIGHUPed

Então, muito mais tarde, execute

zsh> cat my_named_pipe

Mas nada sai do cano. O que há de errado com minha configuração?

PS: Eu nunca usei nohup para funcionar. Eu sempre confio em disown , o que eu não quero fazer como um comando separado neste cenário.

    
por user7000 20.11.2014 / 21:53

2 respostas

4

Quando você faz:

nohup echo "45" > my_named_pipe &

O shell se bifurca. Na criança, abre my_named_pipe para escrever. Esse open() bloqueia até que algo mais abra my_named_pipe para leitura.

Quando você executa exit no processo pai, o filho ainda está bloqueado no open() e ainda não executou nohup .

Assim, ao sair do shell, o shell envia SIGHUP para o filho, que ele não ignora, pois ele ainda não executou nohup .

Basta executar:

(echo 45 > my_named_pipe &)

Ou com zsh :

echo 45 > my_named_pipe &!

&! é o açúcar sintático zsh para disown

Both BASH and ZSH have a nice builtin called disown. It enables user to detach process from the shell in a way much similar to that of nohup. ZSH has a nice sugar for it: you can put &! at the end of the command, and it would be detached. BASH doesn’t have such sugar

http://blog.debiania.in.ua/posts/2013-03-13-fun-with-bash-disown.html

    
por 20.11.2014 / 23:11
2

O problema que você está tendo, e a razão pela qual é dependente do shell, é que o redirecionamento > é processado primeiro e, se ninguém estiver lendo o pipe ainda, ele será bloqueado. Somente após a abertura ser bem-sucedida, o shell executará nohup . Você desconectou enquanto ainda estava bloqueado em aberto, então nohup ainda não havia acontecido e o SIGHUP cancelou o processo em segundo plano. É por isso que disown é melhor. Aplica-se imediatamente ao trabalho.

Da minha tentativa de reproduzir o problema com o bash, parece que o bash não retransmite o SIGHUP de final de sessão para seus filhos, como o zsh, então o trabalho em segundo plano sobrevive.

    
por 20.11.2014 / 22:59