Reference: Signal processing practice in shell scripts the signal trap function of the Linux shell you must know the details in Unix, each type of event that can occur is described by an independent signal, each of which is a small positive integer, such as:
name value description sighup 1 Control terminal discovery suspended or control process death SIGINT 2 3 9 terminating signal
Use: Kill-l to list supported signals
Send signal: kill-signal PID
Sigterm:kill PID equivalent to kill-s SIGTERM PID
such as: Kill-s SIGHUP 1001; Equivalent to KILL-1 1001, one using the signal name, one using the integer representing the signal
Sigkill:sigkill has special abilities that cannot be captured, any process that receives it terminates immediately, kill-9 1001 sometimes needs to stop running scripts, and using Kill-9 <pid> (that is, sending a signal SIGKILL) can sometimes produce Some junk files, so you need to find a way to let the script gracefully exit.
Solution Solutions
Shell scripts can customize their signal handlers with the built-in trap command, which captures signals sent to the current process and executes their own defined functions, rather than performing the system default functions. Note that SIGKILL cannot be captured, why? Because the system always leaves a means to end the process, otherwise if all the signals are captured but not out, then the process can not be killed.
The trap command format is as follows:
' command_list ' signals
Where Command_list is a list of commands that can contain a function that runs after receiving a signal contained in a list of signals. The signals is the list of signals that will be captured.
For example:
Capture SIGINT, output a message and exit, using
' Echo ctrl-c\, now exiting ... exit ' SIGINT
Capture SIGINT, do nothing, ignore the signal, use
"' SIGINT
Resets the SIGINT, even with the system default signal processing function
Trap-sigint
In this case, you can capture the SIGTERM signal and specify a signal handler function to clean up the resource, and then exit when the resource is clean.
Implement
[Email protected]$~>CatSignal.SH #!/bin/Bashtrap'Taskclean; Exit'SIGTERMfunctionTaskOne () {Echo "Now do task one ..." Sleep Ten Echo "TaskOne is done"}functionTasktwo () {Echo "Now do task ..." Sleep Ten Echo "Tasktwo is done"}functionTaskclean () {Echo "Now does task clean ..." Sleep 2 Echo "Taskclean is done"}taskonetasktwo
Run
SH signal. SH dodoesdone
Send a signal to the script when executing TaskOne SIGTERM, the script then executes "sleep", and at the end of sleep the signal processing function is executed instead. Note that the signal processing function is not executed at the end of the TaskOne.
Some instructions for using the trap:
It has three forms corresponding to three different signal response modes.
The first type:
Trap ' commands ' signal-list
When the script receives a signal that is listed in the signal-list manifest, the trap command executes the command in double quotation marks.
The second type:
Trap Signal-list
Trap does not specify any command to accept the default action of the signal. The default action is to end the run of the process.
The third type:
Trap ' signal-list
The trap command specifies an empty command string that allows the signal to be ignored.
Note:trap can only be set for the same signal if multiple traps are set in a shell, such as:
Trap 'echo ' aaaaaaaaaaa "' inttrap 'echo" BBBBBBBBBBB "' INT
Then it will only respond to the last signal setting.
Signal processing (Signal handling) has always played an important role in Linux programming, with almost every system tool used, and the most common function is to signal inter-process communication (especially parent-child processes) and capture SIGINT, SIGTERM Sort of exit signal to do some aftercare (cleanup). There is no need to say in C, you can use the Wait family function, and the shell script also has a trap function to capture the signal--while many people use the trap function, there is such a misunderstanding, these seemingly insignificant small details may finally make your script and your expected behavior completely different.
If no special instructions are given, the shell below refers to Bash as an example.
0. Introduction to trap usage
Although I would like to say that this should be my own view of manpage, but considering that you may be reading the article you do not have Linux on hand, or simply say it.
1 |
USAGE: trap [Action condition ... ] |
That is, when any one of the signals corresponding to the condition list is captured, the action action (used eval action
to execute it) is executed, so the action can be a shell built-in instruction, an external command, a function in the script, and so on. Action is also "" (empty), '-' and so on, respectively, representing the default behavior of ignoring the corresponding signal and resetting the corresponding signal.
1. What is the standard format for condition?
How should the signals in the condition be written? For example, the terminal interrupt signal (usually issued with Ctrl-c), in the end is written SIGINT, INT or 2 (most of the signal corresponding to the system signal number)? Is it uppercase or lowercase?
If you're using the latest version of Bash, you can do this in several ways. And if you need to keep portability in different shells, use uppercase, non-prefixed INT! According to the POSIX standard, the condition of the trap should not be prefixed with the sig and must be in full capitalization, allowing the sig prefix or lowercase to be the extended functionality of some shells. and the number of signals may be different on different systems, so it's not a good idea either.
2. Must the trap be placed on the first line?
A lot of information, especially in Chinese, cannot be argued to indicate that--trap must be placed in the first non-commented line in the script. Is that really the case?
I did not find any instructions related to manpage or POSIX documentation. Even in TLDP's Bash guide for beginners, several examples clearly put the trap in the middle of the script. Finally, I found in this document that the following sentence is often misread:
Normally, all traps was set before other executable code in the shell script was encountered, i.e., at the beginning of the Shell script.
Sure enough, this is just a design routine to ensure that the signal hooks are set up early. In fact, the trap can be placed anywhere in the script depending on your needs. There can also be multiple traps in a script that can define different behaviors for different signals, or modify or delete a defined trap. Further, the trap also has a scope, you can put it in the function, it will only work in this function! You see, the trap behavior is very consistent with UNIX practice.
3. When was the signal handled by the trap?
This is the most important point in this article. When did the signal get processed? More accurately, such as when a script is executing a command and receives a signal, will it be processed immediately, or will it wait for the current command to complete?
I'm not going to explain the answer directly. To let us have a more thorough understanding of the problem, let's do the experiment. Look at the following script, which is often used to explain the trap:
1 2 3 |
#!/bin/bash Trap ' echo ' interrupted! "; Exit ' INT Sleep |
Most tutorials do this, run the script and press CTRL-C. What did you see? The script typed "interrupted!" and stopped running. This may seem normal and intuitive-in this sense, the trap will immediately capture the signal and execute it, regardless of the currently executing command. Many scripts are also written under this hypothesis.
But is that really the case? Let's do another experiment--execute the script at a terminal and open another terminal, use the ps-ef|grepbash
process number of the script to find it, and then kill-SIGINT pid
send the SIGINT signal to the process. What did you see in the original terminal? No response! If you are willing to wait 100 seconds, you will eventually see "interrupted!" being output. This looks like the trap is waiting for the signal to be processed after the current command has ended.
Why is such a contradiction? The problem is actually ctrl-c. The default behavior for a terminal like Bash is this: when CTRL-C is pressed, it sends a SIGINT signal to the current entire process group. And sleep is called by the current script, is the child of the script, the default is in the same process group, so also receive SIGINT and stop execution, return to the main process after the trap capture signal.
This document gives us a more accurate explanation-if an external command is currently executing in the foreground, the trap waits for the signal in the signal queue to be processed after the current command finishes. (Another reason why many tutorials go wrong is that sleep in some shells is a built-in command that can be interrupted.) )
So how should the above example be written in order to achieve the desired effect? There are two ways: first, put sleep in the background, and then use the built-in wait for the end of its execution (see the previous paragraph mentioned in the document); second, violence, a long period of sleep split into a second of the small sleep cycle, which in the case of high precision is also a feasible way.
Signal processing in the shell