Elegant Ways to Do Nothing Forever in Bash – Background Process Techniques

background-processbashshell-scriptstdinstdout

I have a program which produces useful information on stdout but also reads from stdin. I want to redirect its standard output to a file without providing anything on standard input. So far, so good: I can do:

program > output

and don't do anything in the tty.

However, the problem is I want to do this in the background. If I do:

program > output &

the program will get suspended ("suspended (tty input)").

If I do:

program < /dev/null > output &

the program terminates immediately because it reaches EOF.

It seems that what I need is to pipe into program something which does not do anything for an indefinite amount of time and does not read stdin. The following approaches work:

while true; do sleep 100; done | program > output &
mkfifo fifo && cat fifo | program > output &
tail -f /dev/null | program > output &

However, this is all very ugly. There has to be an elegant way, using standard Unix utilities, to "do nothing, indefinitely" (to paraphrase man true). How could I achieve this? (My main criteria for elegance here: no temporary files; no busy-waiting or periodic wakeups; no exotic utilities; as short as possible.)

Best Answer

In shells that support them (ksh, zsh, bash4), you can start program as a co-process.

  • ksh: program > output |&
  • zsh, bash: coproc program > output

That starts program in background with its input redirected from a pipe. The other end of the pipe is open to the shell.

Three benefits of that approach

  • no extra process
  • you can exit the script when program dies (use wait to wait for it)
  • program will terminate (get eof on its stdin if the shell exits).
Related Question