Linux bash陷阱与进程替换 更新
对于我发布的答案,我使用了一个更好的测试用例。我在这里添加了更新的测试用例,以防有人想进一步进行实验:Linux bash陷阱与进程替换 更新,linux,bash,shell,process-substitution,Linux,Bash,Shell,Process Substitution,对于我发布的答案,我使用了一个更好的测试用例。我在这里添加了更新的测试用例,以防有人想进一步进行实验: #!/bin/bash mypts="$( tty )" # main traps trap "echo 'trapped SIGCHLD' >$mypts" SIGCHLD trap "echo 'trapped SIGHUP' >$mypts" SIGHUP trap "echo 'trapped SIGINT' >$mypts" SIGINT trap "ech
#!/bin/bash
mypts="$( tty )"
# main traps
trap "echo 'trapped SIGCHLD' >$mypts" SIGCHLD
trap "echo 'trapped SIGHUP' >$mypts" SIGHUP
trap "echo 'trapped SIGINT' >$mypts" SIGINT
trap "echo 'trapped SIGPIPE' >$mypts" SIGPIPE
trap "echo 'trapped SIGSEGV' >$mypts" SIGSEGV
trap "echo 'trapped SIGSYS' >$mypts" SIGSYS
trap "echo 'trapped SIGTERM' >$mypts" SIGTERM
function h4 {
# function traps
# these mask the main traps
#trap "echo 'trapped h4 SIGCHLD'" SIGCHLD
#trap "echo 'trapped h4 SIGHUP'" SIGHUP
#trap "echo 'trapped h4 SIGINT'" SIGINT
#trap "echo 'trapped h4 SIGPIPE'" SIGPIPE
#trap "echo 'trapped h4 SIGSEGV'" SIGSEGV
#trap "echo 'trapped h4 SIGSYS'" SIGSYS
#trap "echo 'trapped h4 SIGTERM'" SIGTERM
{
# compound statement traps
# these mask the function traps
#trap "echo 'trapped compound SIGCHLD'" SIGCHLD
#trap "echo 'trapped compound SIGHUP'" SIGHUP
#trap "echo 'trapped compound SIGINT'" SIGINT
#trap "echo 'trapped compound SIGPIPE'" SIGPIPE
#trap "echo 'trapped compound SIGSEGV'" SIGSEGV
#trap "echo 'trapped compound SIGSYS'" SIGSYS
#trap "echo 'trapped compound SIGTERM'" SIGTERM
echo begin err 1>&2
echo begin log
# enable one of sleep/while/find
#sleep 63
#while : ; do sleep 0.1; done
find ~ 2>/dev/null 1>/dev/null
echo end err 1>&2
echo end log
} \
2> >(
trap "echo 'trapped 2 SIGCHLD' >$mypts" SIGCHLD
trap "echo 'trapped 2 SIGHUP' >$mypts" SIGHUP
trap "echo 'trapped 2 SIGINT' >$mypts" SIGINT
trap "echo 'trapped 2 SIGPIPE' >$mypts" SIGPIPE
trap "echo 'trapped 2 SIGSEGV' >$mypts" SIGSEGV
trap "echo 'trapped 2 SIGSYS' >$mypts" SIGSYS
trap "echo 'trapped 2 SIGTERM' >$mypts" SIGTERM
echo begin 2 >$mypts
awk '{ print "processed by 2: " $0 }' >$mypts &
wait
echo end 2 >$mypts
) \
1> >(
trap "echo 'trapped 1 SIGCHLD' >$mypts" SIGCHLD
trap "echo 'trapped 1 SIGHUP' >$mypts" SIGHUP
trap "echo 'trapped 1 SIGINT' >$mypts" SIGINT
trap "echo 'trapped 1 SIGPIPE' >$mypts" SIGPIPE
trap "echo 'trapped 1 SIGSEGV' >$mypts" SIGSEGV
trap "echo 'trapped 1 SIGSYS' >$mypts" SIGSYS
trap "echo 'trapped 1 SIGTERM' >$mypts" SIGTERM
echo begin 1 >$mypts
awk '{ print "processed by 1: " $0 }' >$mypts &
wait
echo end 1 >$mypts
)
echo end fnc
}
h4
echo finish
要获取ascii art进程树(在单独的终端中),请执行以下操作:
---
--- 我很难理解信号在bash中是如何传播的,以及哪个陷阱将处理它们 我这里有3个例子。每个示例都使用两种变体进行测试,即任一行未注释。示例由以下伪代码生成:
main_trap
func
compound_statement(additional_traps) > process_redirection(additional_traps)
我试了几次两个品种的每一个例子。我得到的结果很少,我发布了我找到的结果
测试如下所示:
# variation 1:
# trap "echo 'trapped' >/dev/stderr" SIGTERM SIGINT SIGHUP SIGPIPE
begin
^Ctrapped 2
Segmentation fault
# variation 2:
# trap "echo 'trapped'" SIGTERM SIGINT SIGHUP SIGPIPE
begin
^Cend 2
finish
trapped 2
begin
^Ctrapped 2
end 2
finish
begin
^Ctrapped 2
Segmentation fault
# variation 1:
# trap "echo 'trapped' >/dev/stderr" SIGTERM SIGINT SIGHUP SIGPIPE
begin
^Ctrapped 2
end 2
finish
end
trapped 1
trapped
begin
^Ctrapped 2
end 2
finish
end
trapped
begin
^Cend 2
finish
trapped 2
end
trapped inner
trapped
trapped 1
# variation 2:
# trap "echo 'trapped'" SIGTERM SIGINT SIGHUP SIGPIPE
begin
^Ctrapped 2
end 2
finish
trapped inner
trapped 1
trapped
end
begin
^Ctrapped 2
end 2
finish
trapped
end
trapped inner
trapped 1
begin
^Ctrapped 2
end 2
finish
trapped inner
trapped 1
trapped
end
# variation 1:
# trap "echo 'trapped' >/dev/stderr" SIGTERM SIGINT SIGHUP SIGPIPE
begin
^Ctrapped 2
end 2
finish
end
trapped 1
trapped
begin
^Ctrapped 2
end 2
finish
trapped 1
trapped
end
begin
^Cend 2
finish
trapped 2
trapped 1
trapped
end
begin
^Cend 2
finish
end
trapped 2
trapped 1
trapped
begin
^Cend 2
finish
trapped 2
end
trapped
trapped 1
begin
^Cend 2
finish
end
trapped 2
# variation 2:
# trap "echo 'trapped'" SIGTERM SIGINT SIGHUP SIGPIPE
begin
^Cend 2
trapped 2
finish
trapped
end
trapped 1
begin
^Ctrapped 2
end 2
finish
trapped
end
trapped 1
begin
^Ctrapped 2
end 2
finish
trapped 1
trapped
end
测试设置2(2猫):
结果:
# variation 1:
# trap "echo 'trapped' >/dev/stderr" SIGTERM SIGINT SIGHUP SIGPIPE
begin
^Ctrapped 2
Segmentation fault
# variation 2:
# trap "echo 'trapped'" SIGTERM SIGINT SIGHUP SIGPIPE
begin
^Cend 2
finish
trapped 2
begin
^Ctrapped 2
end 2
finish
begin
^Ctrapped 2
Segmentation fault
# variation 1:
# trap "echo 'trapped' >/dev/stderr" SIGTERM SIGINT SIGHUP SIGPIPE
begin
^Ctrapped 2
end 2
finish
end
trapped 1
trapped
begin
^Ctrapped 2
end 2
finish
end
trapped
begin
^Cend 2
finish
trapped 2
end
trapped inner
trapped
trapped 1
# variation 2:
# trap "echo 'trapped'" SIGTERM SIGINT SIGHUP SIGPIPE
begin
^Ctrapped 2
end 2
finish
trapped inner
trapped 1
trapped
end
begin
^Ctrapped 2
end 2
finish
trapped
end
trapped inner
trapped 1
begin
^Ctrapped 2
end 2
finish
trapped inner
trapped 1
trapped
end
# variation 1:
# trap "echo 'trapped' >/dev/stderr" SIGTERM SIGINT SIGHUP SIGPIPE
begin
^Ctrapped 2
end 2
finish
end
trapped 1
trapped
begin
^Ctrapped 2
end 2
finish
trapped 1
trapped
end
begin
^Cend 2
finish
trapped 2
trapped 1
trapped
end
begin
^Cend 2
finish
end
trapped 2
trapped 1
trapped
begin
^Cend 2
finish
trapped 2
end
trapped
trapped 1
begin
^Cend 2
finish
end
trapped 2
# variation 2:
# trap "echo 'trapped'" SIGTERM SIGINT SIGHUP SIGPIPE
begin
^Cend 2
trapped 2
finish
trapped
end
trapped 1
begin
^Ctrapped 2
end 2
finish
trapped
end
trapped 1
begin
^Ctrapped 2
end 2
finish
trapped 1
trapped
end
测试设置3(2只猫,无睡眠子壳):
结果:
# variation 1:
# trap "echo 'trapped' >/dev/stderr" SIGTERM SIGINT SIGHUP SIGPIPE
begin
^Ctrapped 2
Segmentation fault
# variation 2:
# trap "echo 'trapped'" SIGTERM SIGINT SIGHUP SIGPIPE
begin
^Cend 2
finish
trapped 2
begin
^Ctrapped 2
end 2
finish
begin
^Ctrapped 2
Segmentation fault
# variation 1:
# trap "echo 'trapped' >/dev/stderr" SIGTERM SIGINT SIGHUP SIGPIPE
begin
^Ctrapped 2
end 2
finish
end
trapped 1
trapped
begin
^Ctrapped 2
end 2
finish
end
trapped
begin
^Cend 2
finish
trapped 2
end
trapped inner
trapped
trapped 1
# variation 2:
# trap "echo 'trapped'" SIGTERM SIGINT SIGHUP SIGPIPE
begin
^Ctrapped 2
end 2
finish
trapped inner
trapped 1
trapped
end
begin
^Ctrapped 2
end 2
finish
trapped
end
trapped inner
trapped 1
begin
^Ctrapped 2
end 2
finish
trapped inner
trapped 1
trapped
end
# variation 1:
# trap "echo 'trapped' >/dev/stderr" SIGTERM SIGINT SIGHUP SIGPIPE
begin
^Ctrapped 2
end 2
finish
end
trapped 1
trapped
begin
^Ctrapped 2
end 2
finish
trapped 1
trapped
end
begin
^Cend 2
finish
trapped 2
trapped 1
trapped
end
begin
^Cend 2
finish
end
trapped 2
trapped 1
trapped
begin
^Cend 2
finish
trapped 2
end
trapped
trapped 1
begin
^Cend 2
finish
end
trapped 2
# variation 2:
# trap "echo 'trapped'" SIGTERM SIGINT SIGHUP SIGPIPE
begin
^Cend 2
trapped 2
finish
trapped
end
trapped 1
begin
^Ctrapped 2
end 2
finish
trapped
end
trapped 1
begin
^Ctrapped 2
end 2
finish
trapped 1
trapped
end
我的分析是:
我添加所有3个测试用例的主要原因是,有时我会得到一个SEGFAULT
。我把它扔掉了,但不知道它是从哪里来的。这似乎在某种程度上取决于主陷阱中的回声是否重定向到/dev/stderr
(变体1)或不重定向(变体2)
就在Ctrl+C
之后,通常先激活“陷阱2”
,很少激活“结束2”
。这表明(与我最初的想法相反),在处理信号时不涉及过程层次结构。正在运行的进程(复合语句,2个进程替换,在h和h2子shell中,sleep
进程,cat
进程)是并行运行的,无论哪个进程在发送信号时正在运行,都将对其进行处理。出于某种原因,这主要是stderr重定向的进程替换。我假设cat
是主接收器,它没有安装信号处理程序,所以它就死了(这就是为什么我尝试添加2个cat
s,以便第二个可以保持子shell运行)
这就是问题所在,我没有真正的线索知道会发生什么。(我甚至不知道,如果我能做到这一点……)
我认为,信号将从cat
传播到其包含的进程,即安装了信号处理程序的进程替换bashshell,并打印“陷阱2”
现在,我想,故事会在这里结束,一枚戒指被伊西尔多摧毁,佛罗多呆在家里。。。但是没有。不知怎的,它冒出了泡泡,并且成功地杀死了睡眠
。即使有2个cat
s,因此如果其中一个被破坏,子shell仍保持活动状态。我发现很有可能是一个SIGPIPE
杀死了睡眠,因为在没有捕获它的情况下,我看到了一种与我在这里发布的行为不同的行为。但有趣的是,我似乎需要在每个位置设置陷阱
SIGPIPE
,而不仅仅是在睡眠子shell中,或者再一次,它显示了不同的行为
我猜,SIGPIPE
信号到达sleep
,杀死它,因此复合语句中只剩下一个echo
,它执行,子shell完成。stdout重定向的进程替换也被终止,可能是由另一个SIGPIPE
终止的复合语句/函数shell终止的
更有趣的是,有时根本没有显示“trapped 1”
奇怪的是,我没有看到50%的被困2和50%的被困1
我能做什么,我想用这个做什么?
请记住,我的目标是有序地关闭系统/服务/脚本
1) 首先,如我所见,如果这里由sleep
/cat
表示的“业务流程”没有自己的信号处理,那么再多的陷阱也无法避免它们被杀死
2) 信号处理程序不是继承的,每个子shell都必须有自己的陷阱系统
3) 没有什么比进程组更能以公共方式处理信号了,不管信号发生在哪个进程上,它都能完成自己的任务,在那里被杀死的进程的结果可能会在进程树中进一步传播
但我不清楚,如果一个进程不能处理一个信号,它会把它扔到它的外壳中吗?还是另一个信号,传递的是什么?肯定有什么东西通过了,否则信号处理器就不会被触发
在我的理想世界中,trap
将保护安装在外壳内的任何东西不被接收到信号,因此睡眠
-s、猫
-s将被指定的清理功能关闭:杀死
# variation 1
# trap "echo 'trapped' >/dev/stderr" SIGTERM SIGINT SIGHUP SIGPIPE
begin
^Ctrapped 2
trapped 1
trapped
^Ctrapped 2
^CSegmentation fault
# variation 2
# trap "echo 'trapped'" SIGTERM SIGINT SIGHUP SIGPIPE
begin
^Ctrapped 2
trapped 1
trapped
^Ctrapped 2
^CSegmentation fault
^Ctrapped 2
trapped 1
trapped
^Ctrapped 2
Segmentation fault
2> >( cat & )
{
cmd
} \
2> >(logger) \
1> >(logger)
f {
{
cmd
} \
2> >(logger) \
1> >(logger)
}
trap ...
set -m
f &
wait