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.sh

nohup <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 --version

Output 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.pid

kill $(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 & disown

setsid 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.sh

tail -f nohup.out — Watch the default output log live.

tail -f nohup.out

tail -f <custom.log> — Watch a custom log file live.

tail -f worker.log

kill <pid> — Send SIGTERM to a nohup'd process by PID.

kill 4242

kill -9 <pid> — Force-kill (SIGKILL) a process that won't terminate gracefully.

kill -9 4242

pkill -f <pattern> — Kill by command-line pattern when you didn't save the PID.

pkill -f worker.sh

nohup 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 & disown

setsid <command> — Starts the command in a new session — no controlling terminal, so SIGHUP cannot reach it.

setsid ./daemon.sh

tmux 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 all

systemd-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 all

Common 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 %1

ssh -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

  • jobs – list background and suspended jobs of the current shell
  • screen – terminal multiplexer with detachable, reattachable sessions
  • tmux – modern terminal multiplexer with reattach and pane splits