Bash中哪些陷阱会被函数与内置命令继承?
Bash陷阱继承的那些事儿,一次性给你讲明白
我知道你看手册的时候已经get了一部分,但关于“取消陷阱设置”后的继承行为确实容易懵,咱们一步步理清楚:
先回顾手册里的基础规则(你已经理解的部分,再加固下)
先把手册原文摆出来:
当执行除内置命令或Shell函数之外的简单命令时,会在独立的执行环境中调用它……Shell捕获的陷阱会重置为从父Shell继承的值,Shell忽略的陷阱则保持忽略状态。后面还提到子shell的行为与此相同。
给你翻译成大白话:
- 如果你在父Shell里主动设置了某个信号的捕获动作(比如用
trap 'echo "收到退出信号!"' EXIT捕获EXIT信号),那当你启动外部命令或者子shell时,这个捕获动作不会被继承——子环境会把该信号的处理重置回父Shell刚启动时的原始状态(一般就是系统默认行为,比如SIGINT默认是终止进程)。 - 但如果你在父Shell里把某个信号设置为忽略(比如
trap '' SIGINT让脚本无视Ctrl+C),这个忽略状态会直接被子环境继承,不管是外部命令还是子shell,都会跟着忽略这个信号。
重点解决你疑惑的“取消陷阱设置”的行为
这里说的“取消陷阱设置”,指的是用 trap - SIGNAL 命令,把某个信号的处理动作恢复到系统默认状态。那这种状态会不会被继承?咱们用实际例子来说更清楚:
例子1:先设置捕获,再取消,看子环境表现
# 父Shell中先设置捕获SIGINT trap 'echo "父Shell捕获到SIGINT"' SIGINT # 然后取消这个陷阱,恢复默认处理 trap - SIGINT # 启动子shell bash # 在子shell里执行 kill -SIGINT $$ # 结果:子shell直接终止——因为子shell继承了父Shell现在的默认处理状态
例子2:对比“捕获”和“取消”的差异
# 父Shell设置捕获SIGINT trap 'echo "父Shell捕获到SIGINT"' SIGINT # 直接启动子shell bash # 在子shell里执行 kill -SIGINT $$ # 结果:子shell直接终止(没有输出父Shell的捕获信息)——因为子shell把SIGINT的处理重置回了父Shell最初的默认状态,而非继承父Shell的捕获动作
简单总结这个点:当你用 trap - SIGNAL 取消陷阱后,父Shell对该信号的处理就回到了默认值,此时子环境继承的就是这个默认状态,和父Shell刚启动时的行为一致。
最后把所有规则整理成清晰的清单
- 主动捕获的信号(
trap '命令' 信号):子环境(外部命令/子shell)会重置该信号的处理为父Shell启动时的原始状态,不继承捕获命令。 - 设置为忽略的信号(
trap '' 信号):子环境完全继承忽略状态,跟着无视该信号。 - 取消设置的信号(
trap - 信号):子环境继承默认处理状态,和父Shell当前的默认行为一致。
内容的提问来源于stack exchange,提问作者greatBigDot
相关产品推荐
相关产品推荐

