In this post, we discuss common usage of bash trap
to ensure proper cleanup operations in Bash scripts.
It also discusses a common idiom trap cleanup INT TERM EXIT
where other signals such as INT and TERM is also trapped in addition to EXIT.
While such idiom could be valid in some Unix system, it is usually redundant and can be simply wrong (duplicate executions) in most cases, as shown on Mac.
A simple test is provided to verify if such idiom is applicable in your current system.
Standard usage
There is a simple idiom to ensure your bash scripts to always do proper cleanup operations before exiting, even when something goes wrong during execution.
In the context of Java or Python, this is similar to a finally
clause that will execute after any exception is caught during execution.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
|
Putting the cleanup operations at the end of the bash script might not work in cases of error. Since the bash script already stops executing due to some fatal error, those clean up commands might never run.
1 2 3 4 5 6 7 8 9 10 11 12 |
|
For example, in Vertica, you should always run SELECT START_REFRESH()
at the end of a deployment script, regardless of any error encountered during script execution.
It is a good candidate for using trap
statement.
Adding those commands at the end of the script will not work in cases there is an error during deployment, and you might end up with “AHM Does Not Advance”-related errors (see this post).
Trap multiple signals
Note that many online examples for trap
use a list of signals for cleanup tasks like this trap cleanup INT TERM EXIT
, i.e., trapping not only EXIT signal but also INT and TERM signals.
I believe that if EXIT
signal is used, other signals such as INT
or TERM
are redundant for cleanup purposes.
EXIT
or 0 signal is invoked when the shell exits, an event that also happens when an INT
or TERM
signal is received.
It is easy to confirm that with the following short bash script:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
|
As shown above, a lone EXIT
is enough to capture INT
and TERM
signals.
Having said that, I understand that my tests can only verify bash on Mac OSX.
There are probably different shell variants on different operating systems which do not always work that way.
The problem of those trap
examples lies in when someone copies and uses the code directly from the web, without understanding how it works.
Listing multiple signals can make the cleanup
steps executed twice, once for the signal such as TERM
and once for EXIT
, as shown in the modified experiment below.
Not all cleanup steps could be and should be executed twice.
For example, it is almost always true that removing some temporary file/folder should not be executed twice during a cleanup.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
|
In short, you should know how trap
works on your production system before listing multiple signals as its parameters, especially when coupled with EXIT
signal.
Other usage notes
The signal names might be specified with or without prefix SIG
or even with numeric values for signal numbers, e.g., 2 for INT (see list below).
1 2 3 4 5 6 7 8 9 10 11 12 13 |
|
If one of the signals specified in trap
statement is DEBUG
, the list of COMMANDS specified in trap
statement will be executed after every simple command.
This is useful for debugging purpose.
The following example is taken from here:
1 2 3 4 |
|