Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

bash && operator prevents backgrounding over ssh

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?

like image 285
Hinrik Avatar asked Mar 29 '12 16:03

Hinrik


People also ask

What does Bash stand for?

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.

What is in Bash used for?

Bash or Shell is a command line tool that is used in open science to efficiently manipulate files and directories.

Is Bash still used?

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.

Is Bash a language?

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.


1 Answers

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.


Nope, quick experiment in dash shows that 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.
One more trick, not needed if you use the parentheses or braces for this particular case but might be useful in a more general context, where the set of commands to do with && 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.)

like image 110
torek Avatar answered Oct 03 '22 01:10

torek