Docker环境下Bash脚本同时运行多Python脚本失败求助
你的核心问题是Shell脚本执行完后台启动命令后直接退出,导致Docker容器终止,两个Python进程也跟着被杀死。另外还有几个小问题需要修正:
1. 脚本的关键问题
你当前的svc_invoke.sh在启动两个后台进程后,立刻执行状态检查然后退出。Docker容器的生命周期和CMD指定的脚本绑定,脚本一结束,容器就会停止,里面的后台Python进程自然也会被终止——这就是两个脚本都无法正常工作的根本原因。
另外,status=$?只能获取最后一条命令(启动service_scheduler.py的命令)的退出状态,无法检测第一个进程的启动情况;而且后台命令的$?仅表示进程是否成功启动,不代表进程能正常运行。
2. 修复脚本:让脚本等待后台进程
修改svc_invoke.sh,在最后加上wait命令,让脚本一直等待所有后台进程结束,这样容器就不会中途退出:
#!/bin/bash cd /opt # 启动main.py并检查启动状态 /opt/env/bin/python3.11 main.py & if [ $? -ne 0 ]; then echo "Failed to start main.py" exit 1 fi # 启动service_scheduler.py并检查启动状态 /opt/env/bin/python3.11 /api_topics/services/service_scheduler.py & if [ $? -ne 0 ]; then echo "Failed to start service_scheduler.py" exit 1 fi echo "Both processes started successfully" # 等待所有后台进程结束,防止脚本退出导致容器停止 wait
3. Dockerfile的小优化
你Dockerfile里的RUN cd /opt是无效的——每个RUN指令都是独立的容器层,执行完后目录不会保留到下一个RUN。可以用WORKDIR指定默认工作目录,同时合并冗余的RUN指令减少镜像层数:
FROM python:3.11-slim RUN apt-get update && \ apt-get install -y gcc && \ apt-get clean; # 设置默认工作目录,后续命令都基于此目录执行 WORKDIR /opt # 复制项目文件 COPY topic_modelling/ . COPY svc_invoke.sh /svc_invoke.sh RUN chmod 755 /svc_invoke.sh && \ python3.11 -m venv /opt/env && \ /opt/env/bin/python3.11 -m pip install --upgrade pip && \ /opt/env/bin/python3.11 -m pip install wheel && \ /opt/env/bin/python3.11 -m pip install -r requirements.txt ENV PYTHONUNBUFFERED=1 EXPOSE 8000 CMD ./svc_invoke.sh
4. 进阶方案:用Supervisord管理多进程
如果后续需要管理更多进程,或者需要进程崩溃自动重启等监控能力,推荐用supervisord:
步骤1:安装supervisord
在Dockerfile的apt-get install中添加supervisor:
RUN apt-get update && \ apt-get install -y gcc supervisor && \ apt-get clean;
步骤2:创建supervisord配置文件
在项目根目录创建supervisord.conf:
[supervisord] nodaemon=true [program:main] command=/opt/env/bin/python3.11 /opt/main.py directory=/opt stdout_logfile=/dev/stdout stdout_logfile_maxbytes=0 stderr_logfile=/dev/stderr stderr_logfile_maxbytes=0 [program:scheduler] command=/opt/env/bin/python3.11 /opt/api_topics/services/service_scheduler.py directory=/opt stdout_logfile=/dev/stdout stdout_logfile_maxbytes=0 stderr_logfile=/dev/stderr stderr_logfile_maxbytes=0
步骤3:修改Dockerfile
复制配置文件到容器,修改CMD启动supervisord:
COPY supervisord.conf /etc/supervisor/conf.d/supervisord.conf CMD ["/usr/bin/supervisord", "-c", "/etc/supervisor/conf.d/supervisord.conf"]
这样supervisord会负责监控两个Python进程,进程崩溃时自动重启,日志也会统一输出到容器标准输出,方便排查问题。
排查建议
如果修改后仍有问题,可以通过以下方式排查:
- 运行容器时加
-it参数,或用docker logs <容器ID>查看进程输出 - 在Dockerfile中添加
RUN ls /api_topics/services/,验证service_scheduler.py路径是否正确
内容的提问来源于stack exchange,提问作者gautamw3

