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

如何判断Docker容器执行stop后进程是否为优雅终止

判定docker stop终止类型的可行方法

docker stop 默认执行逻辑是先向容器主进程发送SIGTERM信号,若进程在设定的超时周期(默认10秒,可通过-t/--time参数自定义)内未终止,就发送SIGKILL信号强制杀死进程。该命令执行完成后无论终止类型是什么,返回值始终为0,无法直接通过返回值判定结果,可通过以下两种方案实现准确判断:


方案1:结合停止耗时+容器退出码判断(简便首选)

  • 判定逻辑:
    1. 进程被SIGKILL信号强制杀死时,退出码固定为137(计算规则:128 + SIGKILL对应的信号值9);如果进程收到SIGTERM后优雅退出,退出码为进程自身返回值(正常退出一般为0)
    2. 若整个停止操作的耗时大于等于你设置的stop超时时间,同时退出码为137,即可确认是超时后被强制杀死
  • 操作示例:
# 定义停止超时时间,和后续docker stop的-t参数值保持一致即可,默认10秒就填10
STOP_TIMEOUT=10
# 记录停止操作启动时间
START_TS=$(date +%s)
# 执行容器停止
docker stop -t ${STOP_TIMEOUT} test_container
# 记录停止完成时间
END_TS=$(date +%s)
# 拉取容器退出码
EXIT_CODE=$(docker inspect test_container --format='{{.State.ExitCode}}')

# 结果判定
COST_TIME=$((END_TS - START_TS))
if [ $EXIT_CODE -eq 137 ] && [ $COST_TIME -ge $STOP_TIMEOUT ]; then
    echo "判定结果:容器超时后被SIGKILL强制终止"
else
    echo "判定结果:容器收到SIGTERM后优雅终止,进程退出码为$EXIT_CODE"
fi

方案2:通过Docker事件流精准判定(无误差)

  • 判定逻辑:Docker daemon会完整记录容器生命周期的所有事件,包括触发容器退出的具体信号值,直接读取事件里的信号字段即可100%确认终止原因,不会和其他场景的进程退出混淆
  • 操作示例:
# 创建临时文件存储事件记录
TMP_EVENT=$(mktemp)
# 后台启动事件监控,只捕获目标容器的退出事件,提取触发退出的信号值
docker events --filter 'container=test_container' --filter 'event=die' --format '{{.Actor.Attributes.signal}}' > $TMP_EVENT &
MONITOR_PID=$!
# 等待监控进程就绪
sleep 1
# 执行停止操作
docker stop test_container
# 等待事件写入完成后关闭监控进程
sleep 1
kill $MONITOR_PID
# 读取信号值
EXIT_SIGNAL=$(cat $TMP_EVENT)
rm -f $TMP_EVENT

# 结果判定
if [ "$EXIT_SIGNAL" = "9" ]; then
    echo "判定结果:容器被SIGKILL(信号值9)强制杀死,属于超时强杀"
elif [ "$EXIT_SIGNAL" = "15" ]; then
    echo "判定结果:容器收到SIGTERM(信号值15)后优雅退出"
else
    echo "判定结果:容器被其他信号终止,信号值为$EXIT_SIGNAL"
fi

补充注意事项

如果容器主进程没有正确注册SIGTERM信号处理逻辑(比如shell脚本作为1号进程时未用exec启动业务进程,导致SIGTERM被shell忽略),无论执行多少次docker stop都会触发超时强杀,这种场景建议先调整容器入口启动逻辑,保证信号能正确传递给业务进程。

内容的提问来源于stack exchange,提问作者hermit.crab

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 10:39:26