You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

含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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 07:53:17