<p>Shell脚本需通过trap有选择地捕获SIGINT、SIGTERM、EXIT等信号执行清理,临时屏蔽信号用trap '' SIGNAL,临界区后须用trap - 恢复;SIGHUP影响取决于前台/后台及会话关联,推荐nohup/setsid守护。</p>
Shell脚本在运行中常因意外信号(如 Ctrl+C 触发的 SIGINT、终端关闭引发的 SIGHUP)而中断,导致资源未释放、临时文件残留或状态不一致。要提升鲁棒性,关键不是完全禁用信号,而是**有选择地屏蔽、捕获和安全响应**。
trap 是 Shell 处理信号的核心机制。它允许你在指定信号到达时运行一段命令(通常是函数),特别适合做退出前的清理工作。
trap 'command' SIGNAL_NAME 或 trap function_name SIGNAL_NAME
EXIT:确保无论成功失败都执行清理示例:
cleanup() { rm -f /tmp/myapp.pid /tmp/myapp.lock echo "Cleanup done." >&2}trap cleanup EXIT SIGINT SIGTERM
Shell 本身不支持传统意义上的“信号掩码”(如 C 的 sigprocmask),但可通过 trap '' SIGNAL 实现**临时忽略**某信号——这在临界区(如写配置、更新符号链接)中很实用。
trap '' SIGINT:暂时忽略 Ctrl+C,避免中断敏感操作trap - SIGINT(- 表示恢复默认行为)示例(原子更新):
update_config() { trap '' SIGINT SIGTERM # 进入临界区 cp config.new config.tmp mv config.tmp config trap - SIGINT SIGTERM # 恢复信号响应}
当终端关闭或 ssh 断连时,Shell 默认向子进程发送 SIGHUP。但行为取决于进程是否与终端关联:
& 启动):若未脱离会话,仍可能被 hangupnohup、setsid 或重定向 /dev/null 并忽略 SIGHUP安全写法:
# 启动后自动忽略 SIGHUP,并重定向 I/Onohup ./worker.sh > /var/log/worker.log 2>&1 < /dev/null &
信号处理看似简单,但几个细节极易引发问题:
trap 中禁止调用可能被信号中断的复杂命令(如未加锁的 echo 到同一文件多次)exit 非 0 值来“模拟错误”——它不会改变脚本最终退出码,反而干扰调用方判断(...))中的 trap 不继承父 shell,需显式设置set -e 时,trap 不会因命令失败自动触发,必须靠信号或显式 exit