1. Scenario requirements
Scenario: if there is only a temporary command that needs to run for a long time, what is the easiest way to ensure its stable operation in the background?
The origin of hangup name in the early versions of Unix, each terminal would communicate with the system through modem. When the user logs out, the modem will hang up. Similarly, when the modem is disconnected, it will send a hangup signal to the terminal to notify it to close all sub processes.
resolvent:
We know that when the user logs out or the network is disconnected, the terminal will receive a HUP (hangup) signal to close all its sub processes. Therefore, our solution has two ways: either let the process ignore the HUP signal, or let the process run in a new session and become a child process that does not belong to this terminal.
2. nohup command
Nohup is undoubtedly our first idea. As the name suggests, the purpose of nohup is to make the submitted command ignore the hangup signal. Let's take a look at the help information of nohup:
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 the use of nohup is very convenient. Just add nohup before the command to be processed. The standard output and standard error will be redirected to nohup by default Out file. Generally, we can add "&" at the end to run the command in the background at the same time, or use "> filename 2 > & 1" to change the default redirect file name.
nohup example
~]# nohup ping www.ibm.com & [1] 3059nohup: appending output to `nohup.out' ~]# ps -ef |grep 3059 root 3059 984 0 21:06 pts/3 00:00:00 ping www.ibm.comroot 3067 984 0 21:06 pts/3 00:00:00 grep 3059
3. setsid command
nohup can undoubtedly prevent our process from being interrupted by ignoring the HUP signal, but if we think from another angle, if our process does not belong to the sub process of the terminal receiving the HUP signal, it will not be affected by the HUP signal. Setsid can help us do this. Let's take a look at the help information of setsid:
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 the use of setsid is also very convenient. You only need to add setsid before the command to be processed.
setsid example
~]# setsid ping www.ibm.com ~]# ps -ef |grep www.ibm.com root 31094 1 0 07:28 ? 00:00:00 ping www.ibm.comroot 31102 29217 0 07:29 pts/4 00:00:00 grep www.ibm.com
It should be noted that in the above example, our process ID(PID) is 31094, and its parent ID (PPID) is 1 (i.e. init process ID), which is not the process ID of the current terminal. Please compare this example with the parent ID in the nohup example.
4. &
Here's another tip about subshell. We know that including one or more names in "()" can make these commands run in the sub shell, so as to expand many interesting functions. We are going to discuss one of them now.
When we put "&" into "()", we will find that the submitted job is not in the job list, that is, it cannot be viewed through jobs. Let's see why we can avoid the influence of HUP signal.
subshell example
~]# (ping www.ibm.com &) ~]# ps -ef |grep www.ibm.com root 16270 1 0 14:13 pts/4 00:00:00 ping www.ibm.comroot 16278 15362 0 14:13 pts/4 00:00:00 grep www.ibm.com
As can be seen from the above example, the parent ID (PPID) of the newly submitted process is 1 (PID of init process), which is 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.
5. disown
Scenario: we already know that if nohup or setsid is added before the command in advance, the influence of HUP signal can be avoided. However, if we have submitted the command without any processing, how can we remedy it to avoid the influence of HUP signal?
Solution: it's too late to add nohup or setsid. You can only solve this problem through job scheduling and disown. Let's take a look at the help information of disown:
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.
It can be seen that 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 to the background, pause, perform some other operations, and then use fg to put the suspended process back to the foreground (or bg to put the suspended process in the background) to continue running. In this way, we can flexibly switch and run multiple tasks in one terminal, which is particularly useful when debugging code. Because when the code editor is suspended to the background and then placed back, the cursor positioning still stays at the position of the last suspension, avoiding the trouble of relocation.
Use disown -h jobspec to make a job ignore the HUP signal.
Use disown -ah to make all jobs ignore the HUP signal.
Use disown -rh to make running jobs ignore HUP signals.
It should be noted that after using disown, the target job will be removed from the job list. We can no longer use jobs to view it, but we can still find it with ps -ef.
But there is another problem. The operation object of this method is a job. If we add "&" at the end of the command to make it a job and run in the background, then everything will be fine. We can get the list of all jobs through the jobs command. But if you don't run the current command as a job, how can you 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, and then we can use the jobs command to query its job number, and then bg jobspec to put it in the background and continue running. It should be noted that if suspending will affect the running results of the current process, please use this method with caution.
Disown ex amp le 1 (if the command has been put into the background with "&" when submitting the command, you can directly use "disown")
build]# cp -r testLargeFile largeFile &[1] 4825 build]# jobs [1]+ Running cp -i -r testLargeFile largeFile & build]# disown -h %1 build]# ps -ef |grep largeFile root 4825 968 1 09:46 pts/4 00:00:00 cp -i -r testLargeFile largeFileroot 4853 968 0 09:46 pts/4 00:00:00 grep largeFile
Logotdisown ex amp le 2 (if "&" is not used to put the command into the background when submitting the command, you can use CTRL-z and "bg" to put it into the background, and then use "disown")
build]# cp -r testLargeFile largeFile2 [1]+ Stopped cp -i -r testLargeFile largeFile2 build]# bg %1 [1]+ cp -i -r testLargeFile largeFile2 & build]# jobs [1]+ Running cp -i -r testLargeFile largeFile2 & build]# disown -h %1 build]# ps -ef |grep largeFile2 root 5790 5577 1 10:04 pts/3 00:00:00 cp -i -r testLargeFile largeFile2root 5824 5577 0 10:05 pts/3 00:00:00 grep largeFile2
6. screen
Scenario: we already know how to protect the process from HUP signals, but if a large number of such commands need to be run in a stable background, how to avoid doing this for each command?
resolvent:
At this time, the most convenient method is screen. In short, screen provides ANSI/VT100 terminal simulator, which enables it to run multiple full screen pseudo terminals under a real terminal. Screen has many parameters and powerful functions. Here we only introduce its common functions and briefly analyze why using screen can avoid the influence of HUP signal. Let's first look at the help information of screen:
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 establish a session in disconnected mode (and specify its session name).
Use screen -list to list all sessions.
Use screen -r session name to reconnect to the specified session.
Use the shortcut key CTRL-a d to temporarily disconnect the current session.
screen example
~]# screen -dmS Urumchi ~]# screen -list There is a screen on: 12842.Urumchi (Detached) 1 Socket in /tmp/screens/S-root. ~]# screen -r Urumchi
When we connect to the screen session with "- r", we can do whatever we want in this pseudo terminal. We don't have to worry about the impact of HUP signal on our process, and we don't have to add "nohup" or "setsid" before each command. Why? Let me look at the following two examples.
- The process tree of the new process when screen is not used
~]# ping www.google.com & [1] 9499 ~]# pstree -H 9499 init─┬─Xvnc ├─acpid ├─atd ├─2*[sendmail] ├─sshd─┬─sshd───bash───pstree │ └─sshd───bash───ping
We can see that when screen is not used, the bash we are in is a child process of sshd. When ssh is disconnected, the HUP signal will naturally affect all the child processes below it (including our newly established ping process).
- The process tree of the new process after screen is used
~]# screen -r Urumchi ~]# ping www.ibm.com & [1] 9488 [root@pvcent107 ~]# pstree -H 9488 init─┬─Xvnc ├─acpid ├─atd ├─screen───bash───ping ├─2*[sendmail]
It is different when screen is used. bash is the child process of screen, and screen is the child process of init (PID 1). Then, when ssh is disconnected, the HUP signal will not affect the child processes under screen.
7. Summary
Now that several methods have been introduced, we can choose different schemes according to different scenarios. nohup/setsid is undoubtedly the most convenient method when it is needed temporarily. disown can help us remedy the currently running jobs after coming, and screen is the best choice for mass operation.