1. Overview

The nohup command is considered a powerful tool for Linux systems when it comes to administering processes. 

Short for no hang-up, nohup, is essentially used to run commands or processes in the background. This, in general, is to make sure that they continue running in the background even after the terminal session that initiated them has ended. While nohup allows processes to continue running in the background, it can also be used to reattach to an already running process. 

In this tutorial, we’ll discuss how we can achieve this using a few other lesser-known but valuable tools.

2. Reattach to a Running Process

The approach that we’re about to discuss details how to reattach a process without stopping its execution. While doing so, we’ll use the term “reattach” interchangeably to refer to binding a terminal to a process.

2.1. Suspend the Process

So, let’s consider a scenario wherein a process is running in the foreground.

The first step in reattaching an already running process from the current terminal is to suspend the process. To do so, we press the Ctrl+Z keyboard shortcut which in the backend issues a SIGTSTP (Signal Stop) to the process.

At this moment, the process goes into the background and is termed suspended as it’s temporarily stopped or halted:

[1]+  Stopped                 <command>

2.2. Resume Using bg

Essentially, we cannot reattach to a suspended process, so we’ll use the bg command to resume this temporarily stopped process in the background:

$ bg %1

At this stage, we can say that the process is back up and running, but only in the background.

2.3. disown the Process

Now comes the key step in our attempt to reattach to an already running process. This step involves disowning the process so that it gets prevented from being terminated despite the end of the terminal session.

We’ll learn what this technically means with the help of the disown command:

$ disown [-h] [-ar] [jobspec ...]

Here, jobspec refers to the job ID of the process. We can find it by listing all current jobs using the jobs command. Whereas, the -h option marks each job ID so that SIGHUP (Signal Hang-up) isn’t sent to the job if the shell receives a SIGHUP.

We basically disown a process to shield it from termination upon ending the terminal session. Once we’ve disowned a process, we can reattach it to the terminal or another terminal session using tools like reptyr or cryopid.

The next section provides step-by-step instructions for reattaching existing processes using these tools.

3. Reattach Using Modern Tools

reptyr and cryopid are two other lesser-known but powerful tools that we can use to reattach to a running process. Let’s explore each tool in detail.

3.1. Reattach Using reptyr

reptyr is a command-line utility used to reattach a running process to a terminal.

The terminal which is a specific instance of an application running within a user’s session holds the process even after we close the session. This means we can still reattach to the process by reconnecting.

Let’s take a look at a stepwise approach as to how to reattach using reptyr with tmux, short for terminal multiplexer.

The first step is to start the terminal multiplexer of choice, e.g. tmux:

$ tmux

Then, using repytr, we’ll reattach to the backgrounded process:

$ reptyr 4711

To reconnect, we essentially have to detach the terminal multiplexer by pressing CTRL-A D. This closes the user’s SSH session.

Next, we’ll reconnect SSH and attach the terminal to the multiplexer:

$ tmux attach

This reattaching to the terminal enables us to interact with the process again in that terminal session.

3.2. Reattach Using cryopid

cryopid is a more advanced tool that does spot-checking and restores processes. It essentially captures the state of a running process and saves it to a file. Then, we can use this file to resume the process later on, either after a reboot or even on another machine.

To use cryopid to checkpoint the process, we may have to execute the freeze command to create a checkpoint file:

$ ./freeze <output filename> <pid> 
For example:
$ ps -ef|grep 'tail'
root      64208      1  0 01:19 ?        00:00:00 tail -f SystemOut.log
root      64215      1  0 01:20 pts/3    00:00:00 tail -f SystemOut.log
root      64576  64396  0 01:44 pts/5    00:00:00 grep --color=auto tail

$ ./freeze test 64208
Map: 00400000-0040f000 r-xp 00000000 fd:00 16859187   /usr/bin/tail
Map: 0060e000-0060f000 r--p 0000e000 fd:00 16859187   /usr/bin/tail
.....
.....
[+] Process is probably in syscall. Returning EINTR.
Heap was at 0x16e98. Want to be at 0x1930000. offset = 0x1919168
Compressed 2466909 bytes into 109421 bytes (96% compression)
Written image.

$ ls -l test
-rwxr-xr-x 1 root root 192397 Sep 18 01:44 test

This self-extracting executable checkpoint file is the image for the process. This helps restore the process to its previous state, allowing it to continue running.

4. Conclusion

In this article, we’ve explored the versatile world of process management in a Linux environment and touched upon how the utilization of the nohup command handles running processes with finesse.

We also discussed step-by-step how we can reattach to a terminal holding a running process in the Linux environment. Later, we saw how this context provided the pretext for further introducing two lesser-known but highly valuable tools: reptyr and cryopid.

We learned that these tools preserve and migrate the state of critical processes thereby adding substantial flexibility and efficiency to our workflow.