2

I want to use named pipes as asynchrnonous task queues (JMS-like, perhaps).

For example, suppose a client sends some data that I wish to insert into a database, but I want the client to disconnect from the server immediately and the server process pipe the data into a named pipe. Then completely independently read the data from the pipe and perform a SQL insert, which might be very slow - but the client doesn't notice because it gets a response immediately.

As a prototype, I thought this would work (for simplicity the "45" is echoed rather than sent through a netcat client-server pair):

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

Then much later, execute

zsh> cat my_named_pipe

But nothing comes out of the pipe. What's wrong with my setup?

PS: I've never got nohup to work. I always rely on disown which I don't want to do as a separate command in this scenario.

4
  • I can't reproduce this. What version of bash do you have?
    – user41515
    Nov 20, 2014 at 21:17
  • I'm actually using zsh 5.0.2 (though I wrote "bash" above). What happens when you do it? What version of bash do you use? If it works for you I should try that out myself. Nov 20, 2014 at 21:46
  • Oh, it works for me with bash. So zsh is to blame? Nov 20, 2014 at 21:57
  • I'd say bash is to blame for not cleaning up its children when it gets a SIGHUP but if you want to look at it another way I can't stop you
    – user41515
    Nov 20, 2014 at 22:00

2 Answers 2

3

When you do:

nohup echo "45" > my_named_pipe &

The shell forks itself. In the child, it opens my_named_pipe for writing. That open() blocks until something else opens my_named_pipe for reading.

When you run exit in the parent process, the child is still blocked on the open() and has not executed nohup yet.

So upon exiting you shell, the shell sends SIGHUP to the child, which it doesn't ignore since it has not run nohup yet.

Just run:

(echo 45 > my_named_pipe &)

Or with zsh:

echo 45 > my_named_pipe &!

&! is zsh syntactic sugar for 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

3
  • Good information. But the zsh one doesn't work. Is this a drop-in replacement for my command? Or do I need to do something else differently? Nov 20, 2014 at 22:24
  • Ooops, ignore that last post. It works. Thank you :) Nov 20, 2014 at 22:31
  • Is the <> redirect that you mention here not also applicable here?
    – mikeserv
    Nov 21, 2014 at 1:15
2

The problem you're having, and the reason it's shell-dependent, is that the > redirection is processed first, and if nobody is reading the pipe yet, it will block. Only after the open succeeds will the shell execute nohup. You disconnected while it was still blocked in open, so nohup hadn't happened yet and the SIGHUP killed the background process. This is why disown is better. It applies to the job immediately.

From my attempt at reproducing the problem with bash, it seems that bash doesn't relay the session-ending SIGHUP to its children like zsh does, so the background job survives.

2
  • Thanks for the info. Good to know disown is a good solution. Is there any way to use disown "inline" like nohup? Looking at the manpages it doesn't appear so :( Nov 20, 2014 at 22:28
  • Answer to my own followup question: &! Nov 20, 2014 at 22:45

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .