我有一个看起来像这样的代码:
{
trap cleanup SIGHUP SIGINT SIGTERM
function executed() {
if [ ${1} -ne 0 ]
then
echo "Failed!"
cleanup
exit
else
echo "Succeeded!"
fi
}
function cleanup() {
echo "Cleaning up ..."
# deleting some files and stuff like that
}
bunch of code ...
...
} 2>&1 | while IFS= read -r line; do echo "$(date) $line"; done \
>> ldapfe_graceful_$(date '+%Y_%m_%d__%H_%M_%S').log
我无法粘贴我的所有代码,因为我不确定公司在这方面的政策以及所有这些,但最重要的部分都在那里。
我在该脚本运行时按 Ctrl + c,它要么立即停止,要么显示一点 ^C,然后在 5-10 秒后停止,但从未调用清理函数。
我已将所有代码放入 {} 中,以将其很好地重定向到一个文件中(我使用单独的脚本来调用此脚本并进行重定向,但似乎更难杀死该脚本并将信号传播到此脚本,因此我刚刚决定将其全部放在花括号中)。
我确信我遗漏了有关大括号的内容,因为如果我将 trap 和 cleanup 放在 {} 块之外,则会调用 cleanup 函数,但代码的其他部分也应该能够调用它,并且如果它位于 {} 大括号之外。
编辑:我尝试在清理函数之后声明陷阱,但没有改变。
答案1
代码的其他部分应该能够调用清理函数,无论它是在 {} 大括号内部还是外部,只要它在实际调用之前声明(实际上,它与前一个脚本行无关),并且在同一或降低 bash shell 级别 (
$BASH_SUBSHELL
)。(已编辑)如果已经声明了陷阱,则可以调用该陷阱,并且必须在相同或较低的子 shell 级别上声明该陷阱。显然,信号是向下级联的,如下面的代码所示,当您运行它时。
。
#!/usr/bin/env bash
trap "echo ok 0" 2
(
echo subshell: $BASH_SUBSHELL
trap "echo ok 1" 2
(
echo subshell: $BASH_SUBSHELL
trap "echo ok 2" 2;
sleep 100
#now test the trap
)
)
结果:
subshell: 0
subshell: 1
subshell: 2
^Cok 2
ok 1
ok 0
但不是管道:
#!/bin/bash
trap "echo ok 0" 2
{
echo $BASH_SUBSHELL
trap "echo ok 1" 2
} | \
{
trap "echo ok 2" 2
read line; echo $line;
sleep 100
#now Ctrl-c
}
结果:
1
^Cok 2
ok 0
- 大括号构造一个匿名函数。该函数保持 bash shell 级别,但并非在所有上下文中都如此。
分析下面的脚本以进行说明。在终端中运行它并查看它会产生什么。
#!/bin/bash
k=k
msg='echo line: $LINENO, \$k: $k, BASH_SUBSHELL: $BASH_SUBSHELL'
eval $msg
{
k=a
eval $msg
} &
sleep 1
#job %1 should be done by now
jobs
eval $msg
{
k=b
eval $msg
} | {
read line; echo $line;
eval $msg
}
eval $msg
{
k=c
eval $msg
}
eval $msg
{ trap 'echo -e "\nterminating"; exit;' 2;}
sleep 100 #try out the trap by hitting Ctrl-c
- 您的脚本的解决方案是:
A。将陷阱移到第一个之前{
。
b.尝试在第一次{
使用一些智能构造之前移动清理功能eval
(请参阅我的脚本中它是如何工作的)。如果不可能,请尝试在大括号中构建一个代理函数,使其前面的函数更通用,并修补陷阱中调用中缺少的内容。