5 Ways to Keep SSH Sessions Running After Disconnection
In this article, youโll learn five proven ways to keep SSH sessions running after disconnect using screen, tmux, nohup, disown, and setsid, with practical Linux examples.
โ Ravi Saive
SSH, or Secure Shell, is in simple terms a way to remotely access another system through the command line (non-GUI mode).
In more technical terms, when you SSH into another system and run commands, the system creates a pseudo-terminal (PTY) and attaches it to the login shell of the logged-in user.
When you log out or the session times out after being idle, the SIGHUP signal is sent to the pseudo-terminal. All jobs running on that terminal also receive the SIGHUP signal and are terminated.
Jobs whose parent processes were initiated on the pseudo-terminal also receive this signal and are killed.
Only jobs that have been configured to ignore the SIGHUP signal survive session termination. On Linux systems, there are several ways to keep jobs running on the remote server even after logout and session termination, which is exactly what we'll explore in this guide.
Understanding Processes on Linux
Before we dive into the techniques, it's important to understand how different types of processes work on Linux systems, because this knowledge will help you choose the right method for keeping your sessions alive.
Normal Process
Normal processes have a lifespan tied to a session. They start when you run a command and terminate either when they complete their task or when the session ends (like logging out). These processes can be owned by any valid user on the system, including root.
Example: When you run a simple command like ls -la or grep "error" logfile.txt, these are normal processes that start, execute, and finish within your active session.
Here's a practical scenario: Imagine you're copying a large video file from one directory to another using:
cp large_movie.mp4 /backup/
If you disconnect your SSH session while this copy operation is running, the process is immediately killed and the copy stops mid-way. This happens because the process receives the SIGHUP signal when the terminal closes.
Orphan Process
An orphan process is one that initially had a parent process but became "parentless" when its parent unexpectedly died or crashed.
When this happens, the init process (PID 1) or systemd on modern systems automatically adopts the orphaned process as its new parent. Init then waits for these processes to complete or terminate naturally.
Example: Imagine you write a backup script called backup.sh that spawns multiple child processes:
#!/bin/bash
# Main backup script
tar -czf backup1.tar.gz /data/folder1 &
tar -czf backup2.tar.gz /data/folder2 &
tar -czf backup3.tar.gz /data/folder3 &
wait
If the main backup.sh script crashes or gets killed unexpectedly (perhaps due to a memory issue), those three tar compression tasks are still running.
They become orphaned processes, and init automatically becomes their parent, allowing them to continue running until completion.
You can verify this by checking the Parent Process ID (PPID):
ps -ef | grep tar
# You'll see PPID = 1 (init/systemd)
Daemon Process
Daemons are intentionally orphaned processes designed to run continuously in the background. They're deliberately detached from any controlling terminal so they can operate independently of user sessions.
The parent process intentionally exits after spawning the daemon, making init/systemd the parent.
Example: Common daemon processes include:
- Web servers: Apache (
httpd) or Nginx (nginx) constantly run in the background, listening for incoming HTTP requests on ports 80/443. - Database servers: MySQL (
mysqld) or PostgreSQL (postgres) stay running to handle database queries. - SSH daemon: The
sshdprocess itself is always running in the background, waiting for incoming SSH connections.
When you start Apache, for instance:
systemctl start httpd
The main Apache process spawns, detaches from the terminal, and continues running even if you log out. It becomes a daemon with init/systemd as its parent:
ps -ef | grep httpd
# Output shows:
# root 1234 1 ... /usr/sbin/httpd
# ^PPID is 1 (init/systemd)