How to Background or Screen an Already Running Process in Linux (SSH Persistence Techniques)


4 views

We've all been there: you start a critical data_migration.py script via SSH, then realize hours later you forgot to use screen or nohup. Now your terminal session is a single network hiccup away from disaster.

The fundamental limitation stems from Unix process hierarchy. When you start a process interactively:


$ python long_running_script.py
PID 1234

This process (PID 1234) becomes a child of your shell process (PID 1000). Closing the terminal sends SIGHUP to all children unless they're specifically detached.

1. reptyr - The Process Hijacker

The reptyr tool can "steal" running processes:


# Install on Debian/Ubuntu
$ sudo apt install reptyr

# Find your target PID
$ ps aux | grep migration_script

# In a new screen session:
$ screen
$ reptyr 1234

Note: This requires ptrace_scope=0 in /etc/sysctl.d/10-ptrace.conf

2. gdb Debugger Method

For systems where reptyr doesn't work:


$ gdb -p 1234
(gdb) call fork()
$1 = 5678  # New PID
(gdb) call setsid()
(gdb) continue
(gdb) detach

3. Using tmux's attach

If you have tmux available:


$ tmux new -d 'reptyr 1234'
$ tmux attach

For future executions, consider these patterns:


# Using screen from start
$ screen -S migration
$ python script.py
Ctrl-A then D to detach

# Using nohup properly
$ nohup python script.py > migration.log 2>&1 &

Remember: Always test your persistence method with a dummy script before running critical jobs!


We've all been there - you start a long-running data migration script via SSH, then realize hours later you forgot to run it in screen or with nohup. Now you're stuck keeping your terminal open all night.

The fundamental limitation comes from how Unix process hierarchies work. When you start a process:

Terminal (PID 1000) → Shell (PID 1001) → Your Process (PID 1002)

Your process remains connected to the terminal through its parent process. Neither screen nor nohup can change this existing relationship - they only affect new processes.

Option 1: Reptyr - The Magic Tool

Install reptyr (available in most package managers):

sudo apt-get install reptyr  # Debian/Ubuntu
sudo yum install reptyr      # RHEL/CentOS

Then use it to steal your process:

# Start screen first
screen

# In another terminal, find your process ID
ps aux | grep your_script

# Attach it to screen
reptyr PID

Option 2: GDB Debugger Method

For processes that resist reptyr:

# Attach gdb to the process
gdb -p PID

# In gdb:
(gdb) call dup2(open("/dev/null", 0), 0)
(gdb) call dup2(open("/dev/null", 1), 1)
(gdb) call dup2(open("/dev/null", 2), 2)
(gdb) detach
(gdb) quit

This detaches the process from your terminal.

For future runs, consider these approaches:

# Using screen properly
screen -S migration
./long_script.sh
# Ctrl+A then D to detach

# Using tmux (modern alternative)
tmux new -s migration
./long_script.sh
# Ctrl+B then D to detach

# Using nohup correctly
nohup ./long_script.sh > output.log 2>&1 &

If you can't use reptyr or gdb, your options are:

  • Keep the terminal open (not ideal)
  • Restart the process properly (if possible)
  • Use SSH keepalives (temporary solution)