含docker run命令的脚本无法响应SIGINT/SIGTERM终止问题排查
问题原因
当发送SIGINT(如Ctrl+C)或SIGTERM信号时,docker run命令会先向容器内进程发送终止信号,待容器优雅停止后,docker客户端自身会以退出码0正常结束。bash脚本会判定docker run执行成功,因此继续运行后续的echo test failed命令。
而sleep命令在收到SIGINT时会直接以非零退出码终止,且在交互式场景下,Ctrl+C的信号会同步传递给脚本进程,导致整个脚本直接终止,所以不会执行后续echo。
解决方案
通过**信号陷阱(trap)**捕获SIGINT和SIGTERM信号,收到信号时主动停止目标容器并立即终止脚本,阻止后续命令执行。
方案1:后台启动容器+日志实时输出(推荐)
这种方式既保留前台查看日志的体验,又能精准记录容器ID用于终止操作:
#!/bin/bash # 信号处理函数:停止容器并终止脚本 handle_signal() { echo "收到终止信号,正在停止容器..." [ -n "$CONTAINER_ID" ] && docker stop "$CONTAINER_ID" > /dev/null 2>&1 exit 1 } # 绑定SIGINT和SIGTERM信号到处理函数 trap handle_signal SIGINT SIGTERM function run_test() { # 后台启动容器并记录ID CONTAINER_ID=$(docker run -d httpd:latest) # 实时跟踪容器日志,模拟前台运行效果 docker logs -f "$CONTAINER_ID" # 仅当容器正常退出(非信号中断)时,才执行后续逻辑 echo "容器正常退出,测试完成" } run_test
方案2:前台启动容器+指定临时名称
如果需要保持docker run前台运行的原生方式,可以给容器指定临时名称,方便后续定位终止:
#!/bin/bash handle_signal() { echo "收到终止信号,正在停止容器..." docker stop test-httpd-container > /dev/null 2>&1 exit 1 } trap handle_signal SIGINT SIGTERM function run_test() { # 给容器指定唯一临时名称,前台启动 docker run --name test-httpd-container httpd:latest echo "容器正常退出,测试完成" } run_test
效果验证
修改后执行脚本,按下Ctrl+C或触发SIGTERM时,脚本会立即执行信号处理逻辑:停止容器并直接退出,不会执行后续的echo命令。在Jenkins环境中,当构建被终止时,同样会自动清理容器并终止脚本。
内容的提问来源于stack exchange,提问作者Aakarshit Sharma
相关产品推荐
相关产品推荐

