macos shell脚本需用trap捕获sigint、sigterm、sighup等信号并执行清理函数,避免资源泄漏;应为不同信号注册独立handler,注意trap作用域及不可屏蔽信号限制。
macos 的 shell 脚本在后台运行时(比如作为守护进程、定时任务或自动化工具),常需优雅退出:比如收到 ctrl+c(sigint)、系统关机前的 sigterm,甚至 sighup(终端断开)。不处理信号,脚本可能突然中断、留下临时文件、占用资源或破坏数据一致性。关键不是“忽略信号”,而是有意识地捕获、清理、再退出。
用 trap 捕获信号并执行清理逻辑
trap 是 Shell 内置命令,专用于定义信号到达时要运行的代码块。它支持标准 POSIX 信号,也兼容 macOS 的常见行为(如 launchd 发送的 SIGTERM)。
- 基本语法:
trap 'command' SIGNAL_NAME或trap 'command' SIGNAL_NUMBER - 常用信号:
SIGINT(2)、SIGTERM(15)、SIGHUP(1)、SIGQUIT(3) - 推荐写法:把清理动作封装成函数,再用
trap绑定
cleanup() {
echo "正在清理临时文件..."
rm -f /tmp/myscript.lock /tmp/myscript.log
# 可在此关闭子进程、释放端口、发送通知等
}
trap cleanup INT TERM HUP
注意:
trap必须在信号可能到达之前定义;放在脚本开头最稳妥。若清理函数中调用exit,可显式指定退出码(如exit 0表示正常终止)。
区分信号来源,避免误响应
不是所有信号都该触发完全相同的清理。例如:
-
SIGINT(用户按 Ctrl+C)适合快速收尾,但不必等待网络请求完成; -
SIGTERM(系统关机/kill 命令)应更谨慎,比如先通知远程服务、保存状态; -
SIGHUP(终端断开)可能只需重定向日志,不一定要退出。
你可以用 $? 结合 kill -l 判断,但更实用的是——为不同信号注册不同 handler:
部署和使用军舰的 macOS Automator 自动化服务集合。包含 5 个实用工作流:PDF转JPG、PNG重命名并转JPG、图像拼接、解压RAR、顺序命名图像文件。一键安装所有服务到 ~/Library/Services/ 目录。使用场景:(1) "安装我的自动化服务",(2) "部署所有 Automato...
trap 'echo "收到中断,立即退出"; cleanup; exit 130' INT trap 'echo "收到终止请求,尝试优雅关闭"; graceful_shutdown; exit 0' TERM trap 'echo "终端已断开,保持后台运行"; redirect_log' HUP
其中 graceful_shutdown 和 redirect_log 是你自定义的函数。
避免 trap 被覆盖或失效的细节
-
trap默认只对当前 shell 生效,子 shell(如( ... )或管道中的命令)不继承。需要在子进程中重新设置。 - 若脚本用
exec替换当前进程(如exec python3 main.py),原trap会丢失——此时应在被 exec 的程序内部处理信号。 - 不要依赖
trap '' SIGNAL来“屏蔽”信号,尤其SIGKILL(9)和SIGSTOP(19)无法被捕获或忽略,强行忽略某些信号(如SIGTERM)可能让系统无法正常关机。
测试信号响应是否生效
手动发送信号验证最直接:
# 启动脚本(假设叫 monitor.sh) ./monitor.sh & # 查看 PID echo $! # 发送 SIGTERM kill -TERM <pid> # 或发送 SIGINT(模拟 Ctrl+C) kill -INT <pid></pid></pid>
观察终端输出是否打印清理信息、临时文件是否被删除,即可确认 trap 已生效。
不复杂但容易忽略










