When working with remote servers via SSH, maintaining process execution after logout is a common challenge. The typical &
background operator doesn't solve this completely because:
- Processes receive SIGHUP signal when terminal closes
- Child processes may terminate when parent exits
- Session leaders get terminated during logout
Here are the most effective methods to maintain process execution:
# Method 1: nohup (no hangup)
nohup ./long_script.sh > script_output.log 2>&1 &
# Method 2: Using disown
./long_script.sh &
disown -h %1
# Method 3: Screen/Tmux multiplexers
screen -S long_process
./long_script.sh
# Detach with Ctrl+A D
# Method 4: Systemd services (most robust)
sudo tee /etc/systemd/system/long_script.service <<EOF
[Unit]
Description=Long Running Script
[Service]
ExecStart=/path/to/long_script.sh
User=your_username
Restart=on-failure
[Install]
WantedBy=multi-user.target
EOF
sudo systemctl daemon-reload
sudo systemctl start long_script.service
For critical production processes:
# Using setsid to create new session
setsid ./long_script.sh >output.log 2>&1 </dev/null &
# Combining nohup and redirection
nohup stdbuf -oL -eL ./long_script.sh > script_output.log 2>&1 </dev/null &
After launching your process, verify it's running properly:
# Check process status
ps aux | grep long_script
pgrep -fl long_script
# View nohup output if used
tail -f nohup.out
# For systemd services
journalctl -u long_script.service -f
- Always redirect output to files for debugging
- Consider using
timeout
for potentially runaway processes - Implement proper logging within your scripts
- For critical jobs, set up monitoring/alerting
If your process still terminates:
# Check system logs
dmesg | tail
journalctl -xe
# Verify no memory/cpu constraints
free -h
top
When you run a command with &
in bash like this:
./long_running_script.sh &
The process will indeed continue running in the background, but it will still be tied to your SSH session. When you logout, the SIGHUP signal is sent to all processes in the session, terminating them unless handled otherwise.
The most straightforward solution is using nohup
(no hang up):
nohup ./long_running_script.sh > script_output.log 2>&1 &
This does three things:
- Ignores SIGHUP signal
- Redirects stdout to a log file
- Runs in background
For more control, GNU screen is ideal:
# Install screen if needed
sudo apt-get install screen
# Start a new screen session
screen -S long_process
# Run your script
./long_running_script.sh
# Detach from session (Ctrl+A then D)
# Later, reattach with:
screen -r long_process
tmux offers similar functionality with some improvements:
# Install tmux
sudo apt-get install tmux
# Start new session
tmux new -s my_process
# Run script
./long_running_script.sh
# Detach (Ctrl+B then D)
# Reattach later:
tmux attach -t my_process
For production environments, consider creating a systemd service:
# Create service file
sudo nano /etc/systemd/system/long_script.service
[Unit]
Description=Long Running Script
[Service]
ExecStart=/path/to/long_running_script.sh
User=your_username
WorkingDirectory=/path/to/script
Restart=on-failure
[Install]
WantedBy=multi-user.target
# Then enable and start
sudo systemctl enable long_script
sudo systemctl start long_script
Regardless of method, you'll want to check progress:
# For nohup processes
ps aux | grep long_running_script
# For screen/tmux
screen -ls
tmux ls
# For systemd
journalctl -u long_script -f