Linux lets processes (running) run in the background: nohup/&/disown/screen

Keywords: Session Linux ssh network

We often encounter the problem of using telnet/ssh to log on to a remote Linux server and run some long-time tasks, but the task fails due to the instability of the network. How can commands be submitted without interference from local closure of terminal windows/network disconnection? Here are some examples where you can choose different ways to deal with this problem for different scenarios.

nohup/setsid/&

Scene:

If only a temporary command takes a long time to run, what is the easiest way to ensure that it runs stably in the background?

The origin of hangup name
In early versions of Unix, each terminal communicated with the system via modem. When the user logout, the modem hangs up the phone. Similarly, when the modem disconnects, it sends a hangup signal to the terminal to notify it to close all its subprocesses.

Solution:

We know that when a user logout or network disconnects, the terminal receives a HUP signal to shut down all its subprocesses. Therefore, there are two ways to solve this problem: either let the process ignore the HUP signal, or let the process run in the new session and become a sub-process that does not belong to this terminal.

nohup

Nohup is undoubtedly the first way we think about it. As the name implies, the purpose of nohup is to make the submitted command ignore the hangup signal. Let's take a look at nohup's help information first:

NOHUP(1)                        User Commands                        NOHUP(1)

NAME
       nohup - run a command immune to hangups, with output to a non-tty

SYNOPSIS
       nohup COMMAND [ARG]...
       nohup OPTION

DESCRIPTION
       Run COMMAND, ignoring hangup signals.

       --help display this help and exit

       --version
              output version information and exit

It can be seen that nohup is very convenient to use, just add nohup before the command to be processed, standard output and standard error will be redirected to the nohup.out file by default. Usually we can add "&" at the end to run the command in the background at the same time, or we can use "> filename 2 > & 1" to change the default redirected file name.

nohup example

[root@pvcent107 ~]# nohup ping www.ibm.com &
[1] 3059
nohup: appending output to `nohup.out'
[root@pvcent107 ~]# ps -ef |grep 3059
root      3059   984  0 21:06 pts/3    00:00:00 ping www.ibm.com
root      3067   984  0 21:06 pts/3    00:00:00 grep 3059
[root@pvcent107 ~]#

setsid

nohup can undoubtedly avoid interruption of our process by ignoring the HUP signal, but if we think differently, if our process is not a sub-process of the terminal receiving the HUP signal, then naturally it will not be affected by the HUP signal. Setsid can help us do that. Let's first look at setsid's help information:

SETSID(8)                 Linux Programmer's Manual                 SETSID(8)

NAME
       setsid - run a program in a new session

SYNOPSIS
       setsid program [ arg ... ]

DESCRIPTION
       setsid runs a program in a new session.

It can be seen that setsid is also very convenient to use, and only need to add setsid before the command to be processed.

setsid example

[root@pvcent107 ~]# setsid ping www.ibm.com
[root@pvcent107 ~]# ps -ef |grep www.ibm.com
root     31094     1  0 07:28 ?        00:00:00 ping www.ibm.com
root     31102 29217  0 07:29 pts/4    00:00:00 grep www.ibm.com
[root@pvcent107 ~]#

It is worth noting that in the example above, our process ID(PID) is 31094, while its parent ID (PPID) is 1 (i.e. init process ID), which is not the process ID of the current terminal. Compare this example with the parent ID in the nohup case.

and symbol

Here's another tip about subshell. We know that incorporating one or more names in "()" allows these commands to run in a sub-shell, thus expanding many interesting functions, one of which we are now discussing.
When we put "&" in "()", we will find that the submitted jobs are not in the list of jobs, that is to say, they can not be viewed through jobs. Let's see why we can avoid the influence of HUP signal.

subshell Example
[root@pvcent107 ~]# (ping www.ibm.com &)
[root@pvcent107 ~]# ps -ef |grep www.ibm.com
root     16270     1  0 14:13 pts/4    00:00:00 ping www.ibm.com
root     16278 15362  0 14:13 pts/4    00:00:00 grep www.ibm.com
[root@pvcent107 ~]#

As you can see from the above example, the parent ID (PPID) of the newly submitted process is 1 (PID of init process), not the process ID of the current terminal. Therefore, it does not belong to the sub-process of the current terminal, so it will not be affected by the HUP signal of the current terminal.
Page header

disown

Scene:

We already know that adding nohup or setsid before the command can avoid the impact of HUP signals. But if we have submitted the order without any processing, how can we remedy it to avoid the impact of the HUP signal?

Solution:

It's too late to add nohup or setsid, which can only be solved by job scheduling and disown. Let's take a look at disown's help information:

disown [-ar] [-h] [jobspec ...]
    Without options, each jobspec is  removed  from  the  table  of
    active  jobs.   If  the -h option is given, each jobspec is not
    removed from the table, but is marked so  that  SIGHUP  is  not
    sent  to the job if the shell receives a SIGHUP.  If no jobspec
    is present, and neither the -a nor the -r option  is  supplied,
    the  current  job  is  used.  If no jobspec is supplied, the -a
    option means to remove or mark all jobs; the -r option  without
    a  jobspec  argument  restricts operation to running jobs.  The
    return value is 0 unless a jobspec does  not  specify  a  valid
    job.

As can be seen, we can achieve our goal in the following ways.
Flexible Use of CTRL-z
In our daily work, we can use CTRL-z to suspend the current process in the background, perform some other operations, and then use fg to put the suspended process back in the foreground (or bg to put the suspended process in the background) to continue running. This allows us to flexibly switch multiple tasks within a single terminal, which is particularly useful when debugging code. Because when the code editor is hung up in the background and replayed, cursor positioning still stays at the position where it was last hung up, avoiding the trouble of relocation.

  • Disown-h job spec is used to make a job ignore the HUP signal.
  • Disown-ah is used to make all jobs ignore HUP signals.
  • Disown-rh is used to make the running job ignore the HUP signal.

It should be noted that after using disown, the target job will be removed from the list of jobs. We will no longer be able to use jobs to view it, but we will still be able to find it with ps-ef.

But there's another problem. The object of this method is jobs. If we add "&" at the end of the command to make it a job and run it in the background, then everything will be fine. We can get a list of all jobs through the job command. But if the current command is not run as a job, how can we get its job number? The answer is to use CTRL-z (hold down the Ctrl key while holding down the Z key)!

The purpose of CTRL-z is to Suspend the current process, then we can use the job command to query its job number, and then use BG job spec to put it in the background and continue running. It should be noted that if hanging affects the running results of the current process, use this method carefully.

Ex amp le 1 of disown (if the command has been put in the background with "&" when submitting the command, you can use "disown" directly)

[root@pvcent107 build]# cp -r testLargeFile largeFile &
[1] 4825
[root@pvcent107 build]# jobs
[1]+  Running                 cp -i -r testLargeFile largeFile &
[root@pvcent107 build]# disown -h %1
[root@pvcent107 build]# ps -ef |grep largeFile
root      4825   968  1 09:46 pts/4    00:00:00 cp -i -r testLargeFile largeFile
root      4853   968  0 09:46 pts/4    00:00:00 grep largeFile
[root@pvcent107 build]# logout

Ex amp le 2 of disown (if the command is not run in the background using "&" when submitting the command, you can use CTRL-z and "bg" to put it in the background, and then use "disown")

[root@pvcent107 build]# cp -r testLargeFile largeFile2

[1]+  Stopped                 cp -i -r testLargeFile largeFile2
[root@pvcent107 build]# bg %1
[1]+ cp -i -r testLargeFile largeFile2 &
[root@pvcent107 build]# jobs
[1]+  Running                 cp -i -r testLargeFile largeFile2 &
[root@pvcent107 build]# disown -h %1
[root@pvcent107 build]# ps -ef |grep largeFile2
root      5790  5577  1 10:04 pts/3    00:00:00 cp -i -r testLargeFile largeFile2
root      5824  5577  0 10:05 pts/3    00:00:00 grep largeFile2
[root@pvcent107 build]#

screen

Scene:

We already know how to protect processes from HUP signals, but if there are a large number of such commands that need to be run in a stable background, how can we avoid doing this for each command?

Solution:

The most convenient way to do this is screen. Simply put, screen provides ANSI/VT100 terminal simulator, which enables it to run multiple full-screen pseudo-terminals in a real terminal. Screen has many parameters and powerful functions. Here we will only introduce its common functions and briefly analyze why using screen can avoid the influence of HUP signal. Let's first look at screen's help information:

SCREEN(1)                                                           SCREEN(1)

NAME
       screen - screen manager with VT100/ANSI terminal emulation

SYNOPSIS
       screen [ -options ] [ cmd [ args ] ]
       screen -r [[pid.]tty[.host]]
       screen -r sessionowner/[[pid.]tty[.host]]

DESCRIPTION
       Screen  is  a  full-screen  window manager that multiplexes a physical
       terminal between several  processes  (typically  interactive  shells).
       Each  virtual  terminal provides the functions of a DEC VT100 terminal
       and, in addition, several control functions from the  ISO  6429  (ECMA
       48,  ANSI  X3.64)  and ISO 2022 standards (e.g. insert/delete line and
       support for multiple character sets).  There is a  scrollback  history
       buffer  for  each virtual terminal and a copy-and-paste mechanism that
       allows moving text regions between windows.

screen is very convenient to use. There are several common options:

  • Use screen-dmS session name to create a session in disconnected mode (and specify its session name).
  • List all sessions with screen-list.
  • Use screen-r session name to reconnect the specified session.

Use the shortcut key CTRL-a d to temporarily disconnect the current session.

screen example

[root@pvcent107 ~]# screen -dmS Urumchi
[root@pvcent107 ~]# screen -list
There is a screen on:
        12842.Urumchi   (Detached)
1 Socket in /tmp/screens/S-root.

[root@pvcent107 ~]# screen -r Urumchi

When we connect to screen session with'-r', we can do whatever we want in this pseudo-terminal. We don't have to worry about the impact of the HUP signal on our process anymore. We don't have to add "nohup" or "setsid" before each command. Why is that? Let me look at the following two examples.

1. Process tree of new process without screen

[root@pvcent107 ~]# ping www.google.com &
[1] 9499
[root@pvcent107 ~]# pstree -H 9499
init─┬─Xvnc
     ├─acpid
     ├─atd
     ├─2*[sendmail] 
     ├─sshd─┬─sshd───bash───pstree
     │       └─sshd───bash───ping

We can see that our bash is a subprocess of sshd when screen is not used. When ssh disconnects, the HUP signal will naturally affect all the subprocesses below it (including our newly established ping process).

2. The process tree of the new process after using screen

[root@pvcent107 ~]# screen -r Urumchi
[root@pvcent107 ~]# ping www.ibm.com &
[1] 9488
[root@pvcent107 ~]# pstree -H 9488
init─┬─Xvnc
     ├─acpid
     ├─atd
     ├─screen───bash───ping
     ├─2*[sendmail]

When screen is used, bash is a child of screen, and screen is a child of init (PID 1). Then when ssh disconnects, the HUP signal naturally does not affect the sub-processes under screen.

summary

Now that several methods have been introduced, we can choose different solutions according to different scenarios. nohup/setsid is undoubtedly the most convenient method for temporary needs. disown can help us to remedy the current running jobs afterwards, while screen is the best choice for mass operations.

Reprint: https://www.ibm.com/developerworks/cn/linux/l-cn-nohup/

Posted by MrBiz on Tue, 18 Dec 2018 02:51:04 -0800