Long-running backups, reports, and maintenance tasks often need to keep running on the remote host after you reclaim the local terminal. Launching those jobs correctly over SSH avoids babysitting an open session and prevents a local shell from staying attached to work that should continue on its own.
The ssh client normally keeps the session open until the remote command exits and closes its standard streams. Current OpenSSH still uses -f only to fork the client after authentication, and -f already implies -n, so stdin is disconnected but stdout or stderr from the remote command can still keep a backgrounded local ssh process alive until the remote side finishes.
Reliable detached launches therefore need non-interactive authentication, a trusted host key, and explicit remote redirection of stdin, stdout, and stderr before the command is backgrounded. Add nohup when the remote program should ignore a hangup from the remote shell as it exits, but still write output to a chosen log file instead of relying on nohup.out.
$ ssh -o BatchMode=yes user@host.example.net 'printf "ssh-login-ok\n"' ssh-login-ok
BatchMode=yes makes ssh fail instead of waiting for a password, passphrase, or host-key confirmation prompt, which is the behavior needed for unattended background launches.
$ ssh user@host.example.net 'sleep 30'
The local prompt returns only after the remote sleep command exits.
$ ssh -f user@host.example.net 'sleep 120'
Current ssh(1) still documents -f as backgrounding the client just before command execution, and it already implies -n so stdin is redirected from /dev/null.
-f alone does not fully detach the remote job. The local ssh client stays alive in the background until the remote command exits because that command is still attached to the original SSH session.
$ pgrep -af "ssh .*sleep 120" 14862 ssh -f user@host.example.net sleep 120
A matching local ssh process here is expected because the remote sleep command is still using the same session.
$ ssh -f user@host.example.net "sh -c '/usr/local/bin/backup-job.sh >/var/log/backup-job.log 2>&1 < /dev/null &'"
Running the redirection and trailing & inside sh -c keeps the remote shell logic together under a predictable POSIX shell.
If stdout or stderr stays attached to the SSH channel, the local ssh client can remain in the background until the remote process closes those streams.
$ ssh user@host.example.net "pgrep -af 'backup-job.sh'" 14527 /bin/bash /usr/local/bin/backup-job.sh
Checking from a new session confirms that the process no longer depends on the original launcher connection.
$ pgrep -af "ssh .*backup-job.sh"
No output indicates that the remote job is running independently instead of holding a backgrounded local ssh process open.
$ ssh -f user@host.example.net "nohup /usr/local/bin/backup-job.sh >/var/log/backup-job.log 2>&1 < /dev/null &"
nohup ignores the hangup signal, but it does not put the command into the background by itself, so the trailing & and explicit log redirection still matter.