Ric*_*sen 45
从技术上讲,您不能为同一信号设置多个陷阱,但您可以添加到现有陷阱:
trap -p这是一个执行上述操作的bash函数:
# note: printf is used instead of echo to avoid backslash
# processing and to properly handle values that begin with a '-'.
log() { printf '%s\n' "$*"; }
error() { log "ERROR: $*" >&2; }
fatal() { error "$@"; exit 1; }
# appends a command to a trap
#
# - 1st arg: code to add
# - remaining args: names of traps to modify
#
trap_add() {
trap_add_cmd=$1; shift || fatal "${FUNCNAME} usage error"
for trap_add_name in "$@"; do
trap -- "$(
# helper fn to get existing trap command from output
# of trap -p
extract_trap_cmd() { printf '%s\n' "$3"; }
# print existing trap command with newline
eval "extract_trap_cmd $(trap -p "${trap_add_name}")"
# print the new trap command
printf '%s\n' "${trap_add_cmd}"
)" "${trap_add_name}" \
|| fatal "unable to add to trap ${trap_add_name}"
done
}
# set the trace attribute for the above function. this is
# required to modify DEBUG or RETURN traps because functions don't
# inherit them unless the trace attribute is set
declare -f -t trap_add
Run Code Online (Sandbox Code Playgroud)
用法示例:
trap_add 'echo "in trap DEBUG"' DEBUG
Run Code Online (Sandbox Code Playgroud)
Pau*_*ce. 29
编辑:
看来我误解了这个问题.答案很简单:
handler1 () { do_something; }
handler2 () { do_something_else; }
handler3 () { handler1; handler2; }
trap handler3 SIGNAL1 SIGNAL2 ...
Run Code Online (Sandbox Code Playgroud)
原版的:
只需在命令末尾列出多个信号:
trap function-name SIGNAL1 SIGNAL2 SIGNAL3 ...
Run Code Online (Sandbox Code Playgroud)
您可以使用以下方法找到与特定信号关联的功能trap -p:
trap -p SIGINT
Run Code Online (Sandbox Code Playgroud)
请注意,即使它们由相同的功能处理,它也会单独列出每个信号.
通过执行以下操作,您可以添加已知的额外信号:
eval "$(trap -p SIGUSR1) SIGUSR2"
Run Code Online (Sandbox Code Playgroud)
即使有相同功能处理其他附加信号,这也可以工作.换句话说,假设一个函数已经处理了三个信号 - 你可以通过引用一个现有函数再添加两个信号,再添加两个(其中只有一个在结束引号内部显示).
如果你正在使用Bash> = 3.2,你可以做这样的事情来提取给定信号的函数.请注意,它不是完全健壮的,因为可能会出现其他单引号.
[[ $(trap -p SIGUSR1) =~ trap\ --\ \'([^\047]*)\'.* ]]
function_name=${BASH_REMATCH[1]}
Run Code Online (Sandbox Code Playgroud)
然后,如果需要使用函数名等,则可以从头开始重建trap命令.
Jon*_*ler 11
关于您可以做的最好的事情是从trap给定信号的单个命令运行多个命令,但是单个信号不能有多个并发陷阱.例如:
$ trap "rm -f /tmp/xyz; exit 1" 2
$ trap
trap -- 'rm -f /tmp/xyz; exit 1' INT
$ trap 2
$ trap
$
Run Code Online (Sandbox Code Playgroud)
第一行在信号2(SIGINT)上设置陷阱.第二行打印当前陷阱 - 您必须从此捕获标准输出并解析它以获得所需信号.然后,您可以将代码添加到已存在的代码中 - 注意先前的代码很可能包含"退出"操作.第三次调用trap会清除2/INT上的陷阱.最后一个显示没有未完成的陷阱.
您还可以使用trap -p INT或trap -p 2打印特定信号的陷阱.
我喜欢理查德汉森的答案,但我不关心嵌入式功能,所以替代方案是:
#===================================================================
# FUNCTION trap_add ()
#
# Purpose: appends a command to a trap
#
# - 1st arg: code to add
# - remaining args: names of traps to modify
#
# Example: trap_add 'echo "in trap DEBUG"' DEBUG
#
# See: http://stackoverflow.com/questions/3338030/multiple-bash-traps-for-the-same-signal
#===================================================================
trap_add() {
trap_add_cmd=$1; shift || fatal "${FUNCNAME} usage error"
new_cmd=
for trap_add_name in "$@"; do
# Grab the currently defined trap commands for this trap
existing_cmd=`trap -p "${trap_add_name}" | awk -F"'" '{print $2}'`
# Define default command
[ -z "${existing_cmd}" ] && existing_cmd="echo exiting @ `date`"
# Generate the new command
new_cmd="${existing_cmd};${trap_add_cmd}"
# Assign the test
trap "${new_cmd}" "${trap_add_name}" || \
fatal "unable to add to trap ${trap_add_name}"
done
}
Run Code Online (Sandbox Code Playgroud)
这是另一种选择:
on_exit_acc () {
local next="$1"
eval "on_exit () {
local oldcmd='$(echo "$next" | sed -e s/\'/\'\\\\\'\'/g)'
local newcmd=\"\$oldcmd; \$1\"
trap -- \"\$newcmd\" 0
on_exit_acc \"\$newcmd\"
}"
}
on_exit_acc true
Run Code Online (Sandbox Code Playgroud)
用法:
on_exit_acc () {
local next="$1"
eval "on_exit () {
local oldcmd='$(echo "$next" | sed -e s/\'/\'\\\\\'\'/g)'
local newcmd=\"\$oldcmd; \$1\"
trap -- \"\$newcmd\" 0
on_exit_acc \"\$newcmd\"
}"
}
on_exit_acc true
Run Code Online (Sandbox Code Playgroud)
我不喜欢玩这些在最好的时候令人困惑的字符串操作,所以我想出了这样的东西:
(显然您可以针对其他信号对其进行修改)
exit_trap_command=""
function cleanup {
eval "$exit_trap_command"
}
trap cleanup EXIT
function add_exit_trap {
local to_add=$1
if [[ -z "$exit_trap_command" ]]
then
exit_trap_command="$to_add"
else
exit_trap_command="$exit_trap_command; $to_add"
fi
}
Run Code Online (Sandbox Code Playgroud)