nohup — Detach Processes from the Terminal
nohup detaches commands from the terminal so they ignore SIGHUP and keep running after logout – ideal for backups and long-running jobs over SSH.
Start a long-running command over SSH, lose the connection, and the process is usually gone – closing the terminal sends SIGHUP and takes it down with you. nohup shields exactly that signal: the command ignores SIGHUP and keeps running, even after you log out. Combined with & to background it and a redirection for its output, it becomes the classic way to detach a job from the terminal.
Basic Usage
nohup <command> — Run a command immune to hangups. Output is appended to ./nohup.out (or $HOME/nohup.out if cwd is not writable).
nohup ./long-running-task.shnohup <command> & — Run in the background AND immune to SIGHUP — survives terminal close. The typical invocation.
nohup ./backup.sh &nohup <command> arg1 arg2 & — Pass arguments to the command as usual.
nohup rsync -av /data/ user@host:/backup/ &nohup --version — Show GNU coreutils version (BusyBox/macOS nohup do not support --version).
nohup --versionOutput Redirection
nohup <command> > out.log 2>&1 & — Redirect both stdout and stderr to a custom log file instead of nohup.out.
nohup ./worker.sh > worker.log 2>&1 &nohup <command> > out.log 2> err.log & — Separate stdout and stderr into different files.
nohup ./build.sh > build.log 2> build.err &nohup <command> >> out.log 2>&1 & — Append to an existing log file (useful when restarting a job).
nohup ./service.sh >> /var/log/service.log 2>&1 &nohup <command> > /dev/null 2>&1 & — Discard all output entirely. Common for fire-and-forget tasks.
nohup ./cleanup.sh > /dev/null 2>&1 &nohup <command> < /dev/null > out.log 2>&1 & — Also redirect stdin from /dev/null — fully detaches from the terminal (no SIGTTIN if the term is closed).
nohup ./server.sh < /dev/null > server.log 2>&1 &Capturing the PID
nohup <command> > out.log 2>&1 & echo $! — Print the PID of the backgrounded job. $! is the PID of the most recent background process.
nohup ./worker.sh > worker.log 2>&1 & echo $!nohup <command> > out.log 2>&1 & echo $! > task.pid — Save the PID to a file for later management (kill, status checks).
nohup ./worker.sh > worker.log 2>&1 & echo $! > worker.pidkill $(cat task.pid) — Stop a previously started nohup job using the saved PID.
kill $(cat worker.pid)Running Pipelines & Shell Scripts
nohup bash -c '<cmd1> | <cmd2>' & — nohup only protects the FIRST command. Wrap pipelines or redirections in 'bash -c' so the whole pipeline is shielded.
nohup bash -c 'tail -f app.log | grep ERROR > errors.log' &nohup bash -c '<cmd1>; <cmd2>; <cmd3>' & — Run a sequence of commands in one nohup'd shell.
nohup bash -c './backup.sh; ./upload.sh; ./cleanup.sh' &nohup ./script.sh & — Run a script that already contains pipelines/loops. Inside the script, only the script itself needs nohup.
nohup ./deploy.sh > deploy.log 2>&1 &Combining with Other Tools
nohup <command> & disown — Belt-and-braces: nohup ignores SIGHUP, disown removes the job from the shell's table. Survives even if 'shopt -s huponexit' is set.
nohup ./server.sh > server.log 2>&1 & disownsetsid nohup <command> & — Start in a new session AND immune to SIGHUP — fully detached from the terminal session.
setsid nohup ./daemon.sh > daemon.log 2>&1 &nice -n <prio> nohup <command> & — Run a long-living background job at a lower CPU priority.
nice -n 19 nohup ./compress-archives.sh &ionice -c 3 nohup <command> & — Run with idle I/O priority (only uses disk when nothing else needs it).
ionice -c 3 nohup ./backup.sh &ssh user@host 'nohup <command> > out.log 2>&1 &' — Start a remote background job via SSH that survives the SSH session closing.
ssh deploy@web01 'nohup ./restart.sh > restart.log 2>&1 &'Checking & Stopping
ps -ef | grep <command> — Verify the nohup'd process is still running.
ps -ef | grep worker.shtail -f nohup.out — Watch the default output log live.
tail -f nohup.outtail -f <custom.log> — Watch a custom log file live.
tail -f worker.logkill <pid> — Send SIGTERM to a nohup'd process by PID.
kill 4242kill -9 <pid> — Force-kill (SIGKILL) a process that won't terminate gracefully.
kill -9 4242pkill -f <pattern> — Kill by command-line pattern when you didn't save the PID.
pkill -f worker.shnohup vs. Alternatives
<command> & disown — disown alone removes the job from the shell's table. Without nohup, SIGHUP is still delivered if 'huponexit' is on.
long-task & disownsetsid <command> — Starts the command in a new session — no controlling terminal, so SIGHUP cannot reach it.
setsid ./daemon.shtmux new -d -s <name> '<command>' — Run inside a detached tmux session — keeps a TTY for later interactive attachment.
tmux new -d -s build 'make all'screen -dmS <name> <command> — Equivalent for GNU Screen — start in a detached named session.
screen -dmS build make allsystemd-run --user --unit=<name> <command> — Run as a transient systemd user unit — get logging via journalctl and lifecycle control via systemctl.
systemd-run --user --unit=build make allCommon Recipes
nohup <command> > out.log 2>&1 < /dev/null & echo $! — Robust template: detached from stdin, all output to one file, PID printed for later management.
nohup ./worker.sh > worker.log 2>&1 < /dev/null & echo $!Promote a running foreground job — Already-running command in the foreground? Suspend, background, then disown — note: nohup cannot be applied retroactively.
Ctrl+Z
bg
disown -h %1ssh -n -f host 'nohup <cmd> > /tmp/out 2>&1 &' — Fire-and-forget remote start: -n redirects stdin from /dev/null, -f backgrounds ssh after authentication.
ssh -n -f deploy@web01 'nohup ./deploy.sh > /tmp/deploy.log 2>&1 &'Cron without log spam — In cron, nohup is unnecessary (cron has no controlling terminal). Use plain redirection — keep it simple.
*/5 * * * * /usr/local/bin/job.sh > /var/log/job.log 2>&1 Conclusion
nohup is the quickest way to cut a command loose from the terminal: prefix it with nohup, add & to background it, done – the job survives logout and a dropped SSH session. For more robustness, redirect output explicitly (> log 2>&1) instead of relying on nohup.out, detach stdin from /dev/null, and capture the PID with echo $!. Know one limit, though: nohup offers no reattach – if you want to drop back into the running session later, screen or tmux are the better fit, and for genuine, long-lived services the process belongs in a systemd unit rather than behind nohup.
Further Reading
- GNU Coreutils: nohup invocation – official reference for the GNU implementation of nohup
- man7.org: nohup(1) – the Linux manual page for nohup