Getting ssh to execute a command in the background on target machine


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 [email protected] "cd /some/directory; program-to-execute &"

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

8/26/2020 9:57:33 PM

Accepted Answer

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 &
8/26/2008 11:18:41 PM

Redirect fd's

Output needs to be redirected with &>/dev/null which redirects both stderr and stdout to /dev/null and is a synonym of >/dev/null 2>/dev/null or >/dev/null 2>&1.


The best way is to use sh -c '( ( command ) & )' where command is anything.

ssh askapache 'sh -c "( ( nohup chown -R ask:ask /www/ &>/dev/null ) & )"'

Nohup Shell

You can also use nohup directly to launch the shell:

ssh askapache 'nohup sh -c "( ( chown -R ask:ask /www/ &>/dev/null ) & )"'

Nice Launch

Another trick is to use nice to launch the command/shell:

ssh askapache 'nice -n 19 sh -c "( ( nohup chown -R ask:ask /www/ &>/dev/null ) & )"'

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

[email protected] $ screen -t remote-command
[email protected] $ ssh [email protected] # now inside of a screen session
[email protected] $ cd /some/directory; program-to-execute &

To detach the screen session: ctrl-a d

To list screen sessions:

screen -ls

To reattach a session:

screen -d -r remote-command

Note that screen can also create multiple shells within each session. A similar effect can be achieved with tmux.

[email protected] $ tmux
[email protected] $ ssh [email protected] # now inside of a tmux session
[email protected] $ cd /some/directory; program-to-execute &

To detach the tmux session: ctrl-b d

To list screen sessions:

tmux list-sessions

To reattach a session:

tmux attach <session number>

The default tmux control key, 'ctrl-b', is somewhat difficult to use but there are several example tmux configs that ship with tmux that you can try.


I just wanted to show a working example that you can cut and paste:

ssh REMOTE "sh -c \"(nohup sleep 30; touch nohup-exit) > /dev/null &\""

Quickest and easiest way is to use the 'at' command:

ssh [email protected] "at now -f /home/"


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 [email protected] "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 [email protected] "cd /some/directory; nohup myprogram > /dev/null 2>&1"

to redirect all output to /dev/null.


Licensed under: CC-BY-SA with attribution
Not affiliated with: Stack Overflow
Email: [email protected]