Supervisord容器通过Shell脚本管理容器的PID显示异常问题
解决方案:让supervisorctl显示Docker容器的PID
问题核心是Supervisor默认监控的是它启动的子进程(即脚本中的docker start -a进程),而Docker容器的PID属于宿主机的PID命名空间,与Supervisor容器的命名空间隔离。要让supervisorctl status显示容器PID,需要通过PID文件映射的方式实现:
1. 修改启动脚本kafka_start.sh
更新脚本逻辑,在启动容器后将容器的宿主机PID写入指定文件,并添加信号处理确保停止时正确清理:
#!/bin/bash # 定义容器停止与清理函数 stop_container() { docker stop lbrain-kafka > /dev/null 2>&1 rm -f /var/log/supervisor/kafka_container.pid exit 0 } # 捕获Supervisor发送的停止信号,触发容器停止操作 trap stop_container SIGTERM SIGINT # 清理旧容器(如果存在) if docker ps -a --filter name=lbrain-kafka -q | grep -q .; then docker stop lbrain-kafka && docker rm lbrain-kafka fi # 创建并启动Kafka容器 docker create -p 9092:9092 -p 19092:19092 --privileged \ -v /etc/localtime:/etc/localtime:ro \ -v /opt/qihoo/soc/kafka/config/kraft/server.properties:/opt/kafka/config/kraft/server.properties:ro \ -v /data01/entdata/kafka:/tmp/kafka-logs \ -e JAVA_OPTS="$JAVA_OPTS -Duser.timezone=Asia/Shanghai" \ -e KAFKA_HEAP_OPTS="-Xmx1g -Xms1g" \ --name lbrain-kafka kafka:2.13-3.5.1 docker start lbrain-kafka # 获取容器的宿主机PID并写入文件(路径需在Supervisor容器内可访问) CONTAINER_PID=$(docker inspect --format '{{.State.Pid}}' lbrain-kafka) echo $CONTAINER_PID > /var/log/supervisor/kafka_container.pid # 阻塞脚本直到容器停止,避免Supervisor误判进程退出 docker wait lbrain-kafka # 容器停止后清理PID文件 rm -f /var/log/supervisor/kafka_container.pid
2. 修改Supervisor配置kafka.ini
添加pidfile参数指定容器PID文件路径,并配置进程停止相关选项:
[program:kafka] command=sh /opt/supervisor/script/kafka_start.sh environment=JAVA_OPTS="-Dfastjson.parser.safeMode=true" priority=150 autostart=false startsecs=30 user=root redirect_stderr=true stdout_logfile_maxbytes=10MB stdout_logfile_backups=10 stdout_logfile=/var/log/supervisor/kafka_supervisord.log # 指定容器PID文件路径,Supervisor将读取此文件显示PID pidfile=/var/log/supervisor/kafka_container.pid # 停止时终止整个进程组,确保脚本与容器都能正确停止 stopasgroup=true killasgroup=true # 定期检查进程状态,确保PID文件更新后能被识别 check_interval=5
3. 生效配置
重启Supervisor容器或重新加载配置:
docker exec -it lbrain-supervisor supervisorctl reload
原理说明
- Supervisor通过
pidfile选项读取外部文件中的PID,从而在supervisorctl status中显示容器的宿主机PID。 - 脚本通过
docker wait保持运行,避免Supervisor误判进程退出;同时添加信号捕获,确保执行supervisorctl stop kafka时能先停止容器再退出脚本。 - 由于
/var/log/supervisor已挂载到宿主机目录,PID文件会持久化,Supervisor容器内可正常读取。
内容的提问来源于stack exchange,提问作者Eayon
相关产品推荐
相关产品推荐

