views:

6548

answers:

7

This is a follow-on question to the How do you use ssh in a shell script? question. If I want to execute a command on the remote machine that runs in the background on that machine, how do I get the ssh command to return? When I try to just include the ampersand (&) at the end of the command it just hangs. The exact form of the command looks like this:

ssh user@target "cd /some/directory; program-to-execute &"

Any ideas? One thing to note is that logins to the the target machine always produce a text banner and I have ssh keys set up so no password is required.

A: 

Does:

ssh user@target "cd /some/directory; program-to-execute" &

do what you want?

Putting the & outside the quotes causes the ssh command itself to be put in the background. Putting it inside the quotes causes program-to-execute to be put in the background, but the ssh command remains in the foreground.

The inside-the-quote format is useful as a form of poor man's parallel processing:

ssh user@target "cd /some/directory; program-to-execute & other-program &"
Jon Ericson
+7  A: 

I had this problem in a program I wrote a year ago -- turns out the answer is rather complicated. You'll need to use nohup as well as output redirection, as explained in the wikipedia artcle on nohup, copied here for your convenience.

Nohuping backgrounded jobs is for example useful when logged in via SSH, since backgrounded jobs can cause the shell to hang on logout due to a race condition [2]. This problem can also be overcome by redirecting all three I/O streams:

nohup myprogram > foo.out 2> foo.err < /dev/null &
Jax
+2  A: 

Use the -f switch which requests ssh to go to background just before command execution:

ssh -f user@target "cd /some/directory; program-to-execute"
WMR
+2  A: 

If you don't/can't keep the connection open you could use screen, if you have the rights to install it.

hometoast
A: 

So the -f flag from WMR works but is somewhat undesirable since it will end up leaving 20-30 open ssh connections on the main machine.

The nohup suggestions from Jax works if the executed ssh command doesn't include the directory change. For some reason the cd command is giving it headaches and I tried all sorts of different possibilities.

dagorym
A: 

I think you'll have to combine a couple of these answers to get what you want. If you use nohup in conjunction with the semicolon, and wrap the whole thing in quotes, then you get:

ssh user@target "cd /some/directory; nohup myprogram > foo.out 2> foo.err < /dev/null"

which seems to work for me. With nohup, you don't need to append the & to the command to be run. Also, if you don't need to read any of the output of the command, you can use

ssh user@target "cd /some/directory; nohup myprogram > /dev/null 2>&1"

to redirect all output to /dev/null.

A: 

This has been the cleanest way to do it for me:-

ssh -n -f user@host "sh -c \"cd /whereever; nohup ./whatever > /dev/null 2>&1 &\""

The only thing running after this is the actual command on the remote machine

Russ