After trying to figure out why a Capistrano task (which tried to start a daemon in the background) was hanging, I discovered that using &&
in bash over ssh prevents a subsequent program from running in the background. I tried it on bash 4.1.5 and 4.2.20.
The following will hang (i.e. wait for sleep
to finish) in bash:
ssh localhost "cd /tmp && nohup sleep 10 >/dev/null 2>&1 &"
The following won't:
ssh localhost "cd /tmp ; nohup sleep 10 >/dev/null 2>&1 &"
Neither will this:
cd /tmp && nohup sleep 10 >/dev/null 2>&1 &
Both zsh and dash will execute it in the background in all cases, regardless of &&
and ssh. Is this normal/expected behavior for bash, or a bug?
As explained in the Bash Reference Manual, the name bash is an acronym of "Bourne-again SHell" which is a pun on Stephen Bourne, author of the Bourne shell. Bash is a superset of the earlier shell, and generally compatible with Bourne shell programs.
Bash or Shell is a command line tool that is used in open science to efficiently manipulate files and directories.
The biggest advantage to learning Bash is that it's so widely used. Even if you're working in another programming language like Python or Ruby, it's worth learning Bash because many languages support Bash commands to pass data and information to and from your computer's OS.
Bash is a powerful programming language, one perfectly designed for use on the command line and in shell scripts. This three-part series explores using Bash as a command-line interface (CLI) programming language.
One easy solution is to use:
ssh localhost "(cd /tmp && nohup sleep 10) >/dev/null 2>&1 &"
(this also works if you use braces, see second example below).
I did not experiment further but I am reasonably convinced it has to do with open file descriptors hanging around. Perhaps zsh and dash bind the &&
so that this means what has to be spelled as:
{ cd /tmp && nohup sleep 10; } >/dev/null 2>&1
in bash.
echo foo && echo bar >file
only redirects the latter. Still, it has to have something to do with lingering open fd's causing ssh to wait for more output; I've run into this a lot in the past.
&&
are more complex. Since bash seems to be hanging on to the file descriptor inappropriately with &&
but not with ;
, you can turn a && b && c
into a || exit 1; b || exit 1; c
. This works with the test case:
ssh localhost "true || exit 1; echo going on; nohup sleep 10 >/dev/null 2>&1 &"
Replace true
with false
and the echo of "going on" is omitted.
(You can also set -e
, although sometimes that is a bigger hammer than desired.)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With