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

Docker容器内shell脚本trap <action> SIGTERM捕获不生效问题

问题原因

你的脚本存在2个核心错误,直接导致SIGTERM信号无法被正常处理:

  • _term信号处理函数存在语法错误:函数内写的stop()是重新定义一个名为stop的空函数,并非调用你提前写好的服务停止逻辑,就算信号被捕获,也不会执行任何清理操作。
  • 阻塞命令sleep infinity会卡住shell的信号处理流程:多数发行版默认的sh(比如dash)在等待前台外部命令执行时,不会立刻触发注册的trap逻辑,必须等前台命令执行完毕才会处理信号,而sleep infinity永远不会主动退出,直接导致信号捕获逻辑完全无法触发。
修复步骤
  1. 修正信号处理函数的语法错误,补充主动退出逻辑,修改后代码如下:
    _term() {
      echo "Caught SIGTERM signal!"
      stop
      exit 0
    }
    
  2. 替换会阻塞信号的sleep infinity长驻逻辑,使用shell内置的wait命令阻塞,内置命令不会中断trap的信号响应:
    if ! tty --silent
    then
        wait
    fi
    
    如果基础环境不支持wait的长驻逻辑,也可以替换为短周期sleep循环,定期给shell让出信号处理的时机:
    if ! tty --silent
    then
        while true; do sleep 1; done
    fi
    
  3. (推荐优化)将ENTRYPOINT使用的shell从sh替换为bash,信号处理兼容性更稳定,对应Dockerfile配置修改为:
    # 记得提前在镜像构建步骤安装bash,比如Debian/Ubuntu镜像执行apt install -y bash
    ENTRYPOINT ["bash","/home/run.sh"]
    CMD ["start"]
    
  4. (可选优化)在stop函数末尾补充子进程清理逻辑,避免后台残留进程导致容器无法正常退出:
    stop() {
        echo 'Server stopping'
        pkill mapmon.sh
        sudo /etc/init.d/postgresql stop
        sudo /etc/init.d/apache2 stop
        sudo /etc/init.d/renderd stop
        # 清理当前shell启动的所有后台进程
        kill -TERM $(jobs -p) 2>/dev/null
    }
    

完成以上修改后,执行docker stop时容器就会正常打印信号捕获和服务停止的日志,完成清理后主动退出,不会等10秒超时被Docker强制杀死。

内容的提问来源于stack exchange,提问作者Saurabh Batra

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 12:42:17