In infrastructure operations, abnormal process termination following the disconnection of an SSH session to a remote server is a frequent technical issue. Long-running processes (such as Java applications or batch jobs) executed in an interactive shell are forcibly terminated by signals sent from the OS kernel when the controlling terminal (tty/pts) is detached due to terminal window closure or network disconnection.
This behavior relies on the Linux process hierarchy and signal propagation model. Child processes spawned under the session leader (Shell) created during SSH connection receive a hangup signal (SIGHUP) upon session termination and terminate immediately according to their default signal handler.
This article outlines the kernel-level operating principles and practical configuration procedures for process persistence mechanisms achieved through the combination of the nohup utility, which handles SIGHUP signal masking, and the background operator &, which performs shell job control.
Process Structure and SIGHUP Propagation Mechanism
When logging into a Linux system via an SSH client, the OS assigns an interactive shell as the session leader. Executing a command within this shell spawns a child process through the fork() and exec() system calls, placing it in the same process group.
[ SSH Terminal Session ]
│
(Session Leader Created)
│
[ Shell ]
│ (fork / exec)
▼
[ Child Process Group ]
│
┌────────┴────────┐
│ SSH Disconnect / TTY Detach │
└────────┬────────┘
│
▼
Send SIGHUP (Signal 1)
│
┌────────┴────────┐
│ │
Without nohup With nohup
│ │
▼ ▼
Default action: Ignored via SIG_IGN
Process terminated │
▼
Orphan Process Created
│
▼
Adopted by PID 1 (systemd)
(Background Persistence)
1. SIGHUP (Signal ID 1) Generation
When the controlling terminal is disconnected, the kernel detects the termination of the session leader and broadcasts SIGHUP (Signal 1) to all processes belonging to the corresponding process group. Under POSIX standards, the default action for a process receiving SIGHUP is termination.
2. Signal Handler Modification via nohup
The nohup command modifies the signal handler table (Signal Vector) at the kernel level before executing the target binary, setting the action for SIGHUP to SIG_IGN (Signal Ignore). Consequently, even if the parent shell terminates and SIGHUP is delivered, the signal is discarded and the process continues execution.
3. Parent Process Reparenting
Orphaned processes resulting from the destruction of the parent shell have their parent process (PPID) automatically reparented by the Linux kernel to the initialization process, PID 1 (systemd or init). At this stage, the process transitions into a daemon-type process completely detached from terminal dependencies.
Execution Command Structure in Operational Environments
To safely maintain background execution in production environments, detaching standard input/output streams and unifying error logging are essential.
nohup java -jar my-application.jar > app.log 2>&1 &
Parameter Breakdown of Command Components
| Parameter / Syntax | Technical Function and Explanation |
|---|---|
nohup | Registers the signal handler for SIGHUP as SIG_IGN before target binary execution. |
java -jar my-application.jar | The target process command to execute. |
> app.log | Redirects standard output (stdout / file descriptor 1) to the specified log file. |
2>&1 | Merges the output destination of standard error (stderr / file descriptor 2) into the standard output (1) stream. |
& | Moves the process to the background job table at the shell job control layer, releasing standard input (stdin). |
⚠️ Note (Stream Integration):
If 2>&1 is omitted, error logs such as fatal application stack traces will not be recorded in the file, potentially causing a loss of evidence during failure analysis.
Verification Protocol and Terminal Output Logs
This is a verification protocol to confirm whether the process has been correctly detached from the controlling terminal and reparented to PID 1.
$ nohup java -jar my-application.jar > app.log 2>&1 &
[1] 48291
$ pgrep -f my-application.jar
48291
$ ps -ef | grep my-application.jar
appuser 48291 39102 2 14:00 pts/0 00:00:05 java -jar my-application.jar
$ exit
logout
Connection to 192.168.1.50 closed.
# (Re-connect via SSH to verify process status)
$ ps -ef | grep my-application.jar
appuser 48291 1 1 14:01 ? 00:00:12 java -jar my-application.jar
$ ss -tulpn | grep 8080
tcp LISTEN 0 100 *:8080 *:* users:(("java",pid=48291,fd=7))
$ curl -I http://localhost:8080/health
HTTP/1.1 200 OK
Content-Type: application/json
Date: Thu, 01 Oct 2026 14:02:00 GMT
In checking execution results, if the TTY column changes from pts/0 to ? and the PPID (parent PID) changes from the Shell’s PID (39102) to 1, terminal detachment is complete.
Troubleshooting
1. Port Conflicts and Duplicate Execution (java.net.BindException)
Because background processes do not accept standard input, manual termination via Ctrl + C or similar means is not possible. Attempting a restart while the process remains lingering will trigger a port binding error.
Remediation Workflow:
Identify PID of running process:
pgrep -f my-application.jarSend graceful termination signal (
SIGTERM/ Signal 15):kill -15 48291Apply forced termination signal (
SIGKILL/ Signal 9) if resource release fails to complete:kill -9 48291
2. Process Termination by OOM Killer
While nohup configures the process to ignore SIGHUP (Signal 1), the SIGKILL (Signal 9) sent by the Linux OOM Killer upon OS kernel memory exhaustion is non-catchable. If a process suddenly disappears without error logs being recorded in nohup.out, inspect the kernel ring buffer.
dmesg -T | grep -i oom
3. Mitigating Disk Space Exhaustion
Continuing to direct standard output over a long period without log rotation configured will cause disk usage to reach 100%, triggering a system failure. If log rotation is managed by a logging framework, disabling shell output (discarding to /dev/null) is recommended.
nohup java -jar my-application.jar > /dev/null 2>&1 &
Execution Model Comparison
| Item | Simple Background Execution (&) | nohup + & | systemd Service Registration |
|---|---|---|---|
| Prompt Return | Immediate | Immediate | Immediate |
| SIGHUP Tolerance | None (terminates on terminal disconnect) | Yes (ignores signal) | Yes (full process management) |
| Parent PID Transition | Retains PID of execution shell | Reparented to PID 1 | Placed directly under PID 1 |
| Auto-start on OS Reboot | Unsupported | Unsupported | Supported (systemctl enable) |
| Auto-restart on Crash | Unsupported | Unsupported | Supported (Restart=always) |
| Recommended Use Case | Temporary local tasks | Simple background execution in test environments | Persistent microservices in production environments |
Operational Notes
The execution model using nohup and & is an effective, lightweight method to rapidly detach processes from a terminal. However, in production environments where automatic recovery upon OS reboot, dependency control, and automatic restart on process failure are required, transitioning to daemon management via a systemd unit file (/etc/systemd/system/*.service) should be considered. Selecting appropriate signal handling and lifecycle management tailored to operational requirements directly impacts infrastructure stability.