Reliable Background Process Execution on Linux After Terminal Disconnection
Running long-running processes on a remote Linux server often leads to interruptions when SSH sessions terminate unexpectedly. Whether due to network instability, accidental logout, or session timeout, the default behavior of the shell sends a SIGHUP signal to all child processes, causing them to terminate. This article explores several robust methods to ensure processes continue running independently of the terminal session.
Method 1: nohup — Ignore Hangup Signals
The simplest approach is to use nohup, which explicitly instructs the shell to ignore the SIGHUP signal. By default, output is redirected to a file named nohup.out, but this can be customized.
$ nohup wget https://example.com/large-file.zip > download.log 2>&1 &
[1] 2843
The process continues running even after the terminal closes. The & operator runs it in the background, freeing the shell. You can verify its status using ps:
$ ps -o pid,ppid,cmd -p 2843
PID PPID CMD
2843 1324 wget https://example.com/large-file.zip
Method 2: setsid — Run in a New Session
Instead of ignoring SIGHUP, you can detach the process from the terminal entirely by launching it in a new session using setsid. This makes the process a direct child of init (PID 1), eliminating its dependency on the parent shell.
$ setsid curl -o data.tar.gz http://server/data.tar.gz
[1] 3102
Check the process tree:
$ ps -o pid,ppid,comm -p 3102
PID PPID COMM
3102 1 curl
Notice the parent ID is 1 — indicating independence from the terminal session.
Method 3: Subshell with Backgrounding
Wrapping a command in parentheses and appending & creates a subshell that runs in the background. This subshell inherits a new process group and often becomes orphaned, with init as its parent.
$ (rsync -av /source/ /backup/ &)
[1] 1755
Verification shows the same parent-child relationship:
$ ps -o pid,ppid,comm -p 1755
PID PPID COMM
1755 1 rsync
Method 4: disown — Detach Already-Running Processes
If a process is already running and you forgot to use nohup or setsid, you can still rescue it using job control.
First, suspend the process with Ctrl+Z:
$ tar -czf archive.tar.gz /large/directory
^Z
[1]+ Stopped tar -czf archive.tar.gz /large/directory
Then move it to the background and disown it:
$ bg %1
[1]+ tar -czf archive.tar.gz /large/directory &
$ disown -h %1
The job is now detached from the shell. It won't receive SIGHUP upon logout, and jobs will no longer list it — though ps still shows it running.
Method 5: screen — Persistent Terminal Sessions
For managing multiple long-running tasks, screen provides a full terminal multiplexer. It creates a virtual session that survives disconnection.
Create a detached session:
$ screen -dmS data-sync
List active sessions:
$ screen -ls
There is a screen on:
4012.data-sync (Detached)
Reattach to resume work:
$ screen -r data-sync
Inside the session, run any command normally — no special prefixes needed. Detach with Ctrl+A followed by D.
Process tree comparison reveals why this works:
- Without screen:
sshd → bash → ping— ping is a child of the SSH session. - With screen:
sshd → screen → bash → ping— screen is a child of init, so it survives SSH termination.
This isolation ensures all processes within the screen session remain active regardless of network conditions.