Surviving the terminal close
A background job remains attached to several shell and terminal contracts. On logout it may receive SIGHUP, keep a closed terminal as a stream, or continue without a useful owner. These tools change different parts of that relationship:
nohup ./script &— start with no-hangup. SIGHUP is ignored. Output goes tonohup.outin the current dir../script & disown— start, then detach the most recent job from the shell's job table.setsid ./script &— start in a new session (decoupled from the controlling terminal entirely).
Don't forget the streams
Terminal-bound input and output can fail, block, or disappear after disconnection. Redirect them deliberately when a detached command should not interact with the terminal:
nohup ./script > out.log 2>&1 &The right tool for long-running stuff
For things you'll come back to: tmux new -s build './script.sh' + tmux attach -t build later. The session keeps a pseudo-terminal alive even when nobody's looking.
For real services, use the platform's service manager, such as launchd on macOS or systemd on Linux. The service declaration should own startup, restart policy, environment, logs, and stop behavior.
Check if a backgrounded job is alive
kill -0 PID && echo alive
ps -p PIDkill -0 sends no signal. Success means the caller can address a process with that PID; failure can mean no such process or insufficient permission. It does not prove that the process is healthy or doing useful work.
nohup is not a restart manager
nohup changes HUP handling and some stream defaults; it does not restart failure or launch after reboot. Important work still needs status and logs, while long-lived services belong to launchd or systemd.
Separate existence from health
kill -0 PID checks addressability and permission, not progress or useful output. Pair it with log time, output growth, or an application health check.