Trap: Difference between revisions
No edit summary |
No edit summary |
||
Line 7: | Line 7: | ||
* [[Bash#Built-In_Commands|bash]] | * [[Bash#Built-In_Commands|bash]] | ||
* [[Handling Signals in bash]] | * [[Handling Signals in bash]] | ||
* [[Linux Signals]] | |||
=Overview= | =Overview= | ||
"trap" statement is a bash facility that allows for code execution upon catching specific signals. A common usage in shell scripts is to prevent a script to exit untimely when the user types a keyboard abort sequences, but run cleanup code instead. Conceptually, the trap facility is similar to the Java "finally" construct. | "trap" statement is a bash facility that allows for code execution upon catching specific signals. A common usage in shell scripts is to prevent a script to exit untimely when the user types a keyboard abort sequences, but run cleanup code instead. Conceptually, the trap facility is similar to the Java "finally" construct. | ||
=Syntax= | =Syntax= | ||
Line 19: | Line 19: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
One or more signals can be listed. The signals can be listed with or without "SIG" prefix ( | One or more signals can be listed. The signals can be listed with or without "SIG" prefix (SIGKILL and KILL are equivalent) or using their numeric correspondents. | ||
Revision as of 22:01, 23 July 2020
External
- https://www.linuxjournal.com/content/bash-trap-command
- http://tldp.org/LDP/Bash-Beginners-Guide/html/sect_12_02.html
Internal
Overview
"trap" statement is a bash facility that allows for code execution upon catching specific signals. A common usage in shell scripts is to prevent a script to exit untimely when the user types a keyboard abort sequences, but run cleanup code instead. Conceptually, the trap facility is similar to the Java "finally" construct.
Syntax
trap <commands> <signals>
One or more signals can be listed. The signals can be listed with or without "SIG" prefix (SIGKILL and KILL are equivalent) or using their numeric correspondents.
Example:
trap 'rm -f ./lock' EXIT
Global variables declared before the trap declaration are correctly resolved when present in a single-quote quoted string (even if single-quotes are used, the single quote semantics when used in bash command line is different from that in effect here). For example, the following code:
a=hello
trap 'echo ${a}' EXIT
produces:
hello
Variable resolution is done at the time of execution, not declaration, so the following:
trap 'echo ${a}' EXIT
a=hello
also produces:
hello
Experiment with local variables. This works, explain this:
local chart_dir=blah
trap 'rm -rf '${chart_dir}'/tmpcharts; echo chart dir: ${chart_dir}' EXIT
produces:
chart dir: blah
This seems to work for local variables:
trap 'rm -rf '${tmp_dir}' && debug '${tmp_dir}' removed; rm -rf '${chart_dir}'/tmpcharts && debug '${chart_dir}'/tmpcharts removed' EXIT
Special Bash Signals
"EXIT" in the example above is not a Linux signal. Bash provides this psuedo-signal, which is executed when the script exits; this can be used to make sure that your script executes some cleanup on exit.
Other bash pseudo-signals:
- DEBUG
- RETURN
- ERR
For a list of signals that can be handled, see:
Also see:
Only One Code Sequence (Latests) Executes
If multiple code sequences are declared with trap
, only the last one is executed. The following example:
trap 'echo A' EXIT
trap 'echo B' EXIT
produces:
B
Behavior on Being Invoked from Sub-Shells
If code is registered with trap
to react to EXIT in a sub-shell, or in a function that is invoked in a sub-shell, then the registered code will be executed when the sub-shell, and not the top-level invoking shell, exists.
The following code:
$(trap 'echo "a" 1>&2' EXIT)
echo "b"
will display:
a
b
Note that the output should be sent to stderr in the trap code - if the output is sent to stdout, the output is lost, even if the code executes.
Example
Delete Temporary Directory on Exit
local tmp_dir
local preserve_tmp_dir=false
tmp_dir=$(get-tmp-dir) || exit 1
if ${preserve_tmp_dir}; then
debug "temporary directory ${tmp_dir} will be preserved on exit"
else
trap "rm -rf ${tmp_dir} && debug deleted temporary directory ${tmp_dir} || warn failed to delete temporary directory ${tmp_dir}" EXIT && \
debug "registered temporary directory ${tmp_dir} cleanup procedure"
fi
TODO
Reactive Wait Container
Investigate usefulness in case of a reactive wait container. Also see Docker Concepts - Container Exit.
CMD exec /bin/bash -c "trap : TERM INT; sleep infinity & wait"
Other Usage Patterns
trap "rm -f /tmp/blah" 0 2 3 5 10 13 15
Wrap the whole trap functionality in a function
trap _trap SIGTERM
function _trap() {
...
}