I have 2 computers, localpc and remoteserver.

I need localpc to execute some commands on remoteserver. One of the things it needs to do is start a backup script that runs for a number of hours. I would like the command on localpc to “fire” and then be running totally independent on remoteserver, like localpc was never there in the first place.

This is what I have done so far:

remoteserver contains has the script:


localpc is scheduled to run this:

ssh root@remoteserver 'nohup /root/backup.sh' &

Am I doing this the right way? Is there a better way to do this? Will I run into any trouble doing it this way?


7 Answers 7


Close, but not exactly.

Independently of any terminal

ssh root@remoteserver '/root/backup.sh </dev/null >/var/log/root-backup.log 2>&1 &'

You need to close all file descriptors that are connected to the ssh socket, because the ssh session won't close as long as some remote process has the socket open. If you aren't interested in the script's output (presumably because the script itself takes care of writing to a log file), redirect it to /dev/null (but note that this will hide errors such as not being able to start the script).

Using nohup has no useful effect here. nohup arranges for the program it runs not to receive a HUP signal if the program's controlling terminal disappears, but here there is no terminal in the first place, so nothing is going to send a SIGHUP to the process out of the blue. Also, nohup redirects standard output and standard error (but not standard input) to a file, but only if they're connected to a terminal, which, again, they aren't.

Detaching from a terminal

 aaron@localpc$ ssh root@remoteserver
 root@remoteserver# nohup /root/backup.sh </dev/null &
 nohup: appending output to `nohup.out'
 [1] 12345
 root@remoteserver# exit

Use nohup to detach the script from its controlling terminal so that it doesn't receive a SIGHUP when the terminal disappears. nohup also redirects the script's standard output and standard error to a file called nohup.outif they're connected to the terminal; you have to take care of standard input yourself.

Keeping a remote terminal

If you want to keep the command running in a remote terminal but not have it attached to the SSH session, run it in a terminal multiplexer such as Screen or Tmux.

ssh root@remoteserver 'screen -S backup -d -m /root/backup.sh'

You can later reconnect to the terminal where the script is running by invoking screen -S backup -rd as root on that machine.

Automating one remote command

For slightly better security, don't open direct remote root logins too widely. Create a special-purpose key pair and give it a forced command in /root/.ssh/authorized_keys. The contents of the public key file is AAAA…== wibble@example.com; add a comma-separated list of options including command="…" which specifies that the key can only be used to execute this specific command. Be sure to keep the options and the key all on one line.

command="/root/backup.sh </dev/null >/dev/null 2>/dev/null &",no-port-forwarding,no-agent-forwarding,no-x11-forwarding,no-pty,no-user-rc AAAA…== wibble@example.com
  • I have tried the first command you listed. It does not background on the box that executed the command. The cursor just sits there and waits for completion... perhaps it's a bug?
    – LVLAaron
    Jan 31, 2012 at 13:21
  • You might need to redirect stdin to /dev/null on the remote system. That may be why ssh isn't exiting.
    – KeithB
    Jan 31, 2012 at 20:20
  • I would add the -f option to get ssh to ‘background’ (i.e. terminate, close connections) on the local side. This will work in conjunction with the &. nohup is optional in this case, but you might consider using setsid instead.
    – Alexios
    Feb 1, 2012 at 9:36
  • @KeithB Redirecting stdin is part of it, but I also need to redirect stdout and stderr: nohup won't do it here because they're not terminals, and in fact nohup isn't useful here. Feb 1, 2012 at 10:57
  • 1
    @erikbwork Please note that I have absolutely no clue about those things, but following the discussion and the comments: Gilles does not use the -t option in his commands, so no pseudo terminal will be established, neither at the client nor at the server side. Therefore, no HUP will be sent.
    – Binarus
    May 15, 2017 at 18:30

You should probably use screen on the remote host, to have a real detached command:

ssh root@remoteserver screen -d -m ./script
  • I like this idea. When the script finishes, screen will still be running through... and I'd have to somehow reconnect to it next time I wanted to run it, right?
    – LVLAaron
    Feb 1, 2012 at 10:06
  • @AaronJAnderson: no, given that the command is not a shell, when it terminates also that screen session terminates.
    – enzotib
    Feb 1, 2012 at 10:12

The standard recipe for running a remote command from a remote login like SSH is the following:

nohup command </dev/null >command.log 2>&1 &

If command is a shell script that takes care of logging to a file itself, then you could change command.log to /dev/null. Once you start this, log off right away.

You need everything on that line.

nohup tells the shell not to disturb the process if the login session is disconnected.

</dev/null tells it never to wait for input

>command.log tells it to send any messages to this named log file

2>&1 tells it to send any stderr messages to the same log file. In some cases it is better to have two files, the second one to collect error messages, and the first to collect normal activity messages. That can make it easier to verify that everything worked correctly.

& tells it to detach this process and run it in the background as a daemon process.


This thread was very helpful but my solution had to be a bit different.

I don't like the screen solution because it leaves a screen process running which I don't need. The redirections and nohups used like this:

ssh root@remoteserver '/root/backup.sh </dev/null >/var/log/root-backup.log 2>&1 &'

were NOT working for me when used with the ssh command.

I created a wrapper script on the remote machine which runs the actual script. The wrapper script sets the redirection and nohup. Something like this:

nohup backup.sh > /dev/null 2>&1 &

Then on my client machine I run (notice no redirection):

# ssh remotemachine "backupwrapper.sh"

The ssh command immediately returns, the connection is terminated and the script is left running.


As Nils says, it's a security risk to allow root to log in via ssh. And I advise against running any substantial job on a machine without a log. If anything goes wrong, you'll wish you had some troubleshooting messages. There are other answers showing you how to do that. But here's how I recommend accomplishing just what you asked for. It's all built into sh(1). No need for GNU screen (although I think that's a clever solution). Append this string to your command: >&- 2>&- <&- &. >&- means close stdout. 2>&- means close stderr. <&- means close stdin. & means run in the background, e.g.

$ ssh myhost 'sleep 30 >&- 2>&- <&- &'
# ssh returns right away, and your sleep job is running remotely

You should background the remote command on remoteserver. The way you do it will background the ssh-command on localpc.

Apart from that it is a bad idea to allow root-ssh.

So setup on remoteserver: A sudoers line that will run /root/backup.sh as root by user backup.

You could create that user without "good" password.

Put the command sudo /root/backup.sh & as command into ~backup/.ssh/authorized_keys — together with the public key from localpc (whoever triggers that script).

#screen -d -m -S BACKUP ssh root@remoteserver /root/backup.sh
  • 2
    That's not very useful: if the SSH connection dies, the script's stdout and stderr will be closed, which may cause trouble. Screen should be running on the remote machine (as in enzotib's answer). Feb 1, 2012 at 10:54

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.