如何终止父脚本input.sh及其调用的Docker容器所有进程?
如何同时终止input.sh脚本及Docker容器的所有进程
好的,我来帮你解决这个问题——要同时终止input.sh脚本和它启动的Docker容器的所有进程,我们可以分脚本内自动处理和手动事后处理两种场景来操作:
一、在input.sh中添加自动终止逻辑(推荐)
这种方式能让脚本在收到终止信号(比如Ctrl+C)时,自动先停止Docker容器,再退出自身,无需手动查找PID。你可以修改input.sh如下:
#!/bin/sh input_variable_docker=folder # 定义清理函数:停止容器并退出脚本 cleanup() { echo "正在停止Docker容器..." # 停止容器,忽略错误(比如容器已经提前退出) docker stop "$CONTAINER_ID" > /dev/null 2>&1 echo "脚本已终止" exit 0 } # 捕获常见的终止信号(Ctrl+C触发SIGINT,kill命令触发SIGTERM) trap cleanup SIGINT SIGTERM # 后台启动容器并记录容器ID(原来的前台运行会阻塞脚本,所以加-d让它后台跑) CONTAINER_ID=$(docker run -d -t --rm -v /mnt/data/:/home/user/data/ -e INPUT_IMAGE="$input_variable_docker" my_process /home/desuser/processing_scripts/run_script_docker.sh) # 可选:如果需要脚本一直等待容器完成任务再退出,加上这行 docker wait "$CONTAINER_ID"
使用方式
运行修改后的input.sh后,当你按下Ctrl+C,或者用kill <脚本PID>终止脚本时,脚本会自动调用cleanup函数停止容器,然后自身退出,完全清理所有相关进程。
二、手动终止已运行的脚本和容器
如果脚本已经在运行,你可以手动获取PID并一次性终止:
获取input.sh的PID:
SCRIPT_PID=$(pgrep -f input.sh)获取对应的Docker容器ID:
可以根据镜像名过滤(你的镜像是my_process):CONTAINER_ID=$(docker ps --filter "ancestor=my_process" -q)同时终止容器和脚本:
docker stop "$CONTAINER_ID" && kill "$SCRIPT_PID"
补充说明
- Docker容器停止时,会先向容器内的PID 1进程发送
SIGTERM信号,如果进程没有在10秒内退出,会发送SIGKILL强制终止,容器内的所有子进程也会被自动清理(因为Docker的PID命名空间特性)。 - 如果你的容器是前台运行的(没加
-d),脚本会被容器进程阻塞,这时候脚本的PID就是父进程,容器进程是它的子进程,你可以用pkill -P <脚本PID>来杀死所有子进程,再杀死脚本本身:SCRIPT_PID=$(pgrep -f input.sh) pkill -P "$SCRIPT_PID" && kill "$SCRIPT_PID"
内容的提问来源于stack exchange,提问作者sylar_80




