Supervisord 无法管理 daemonized 进程,因其依赖子进程 PID 跟踪,而 daemon 进程 fork 后脱离控制树,导致状态异常、无法重启;必须禁用程序自身 daemon 模式并配置 foreground 运行。

Supervisord 在 Linux 上不能直接管理 daemonized 进程(即自己 fork 到后台的进程),否则会丢失进程控制权,导致 supervisorctl status 显示 STARTING 或 UNKNOWN,且无法自动重启。
为什么 supervisord 会“看不见”你的进程
Supervisord 通过跟踪子进程 PID 来管理生命周期。如果被托管程序自行调用 fork() 并退出父进程(典型如 redis-server /etc/redis.conf、nginx -c /etc/nginx/nginx.conf),supervisord 启动的只是“启动器”,真正的 worker 进程已脱离其控制树。
常见现象包括:
-
supervisorctl status中状态长期卡在STARTING,几秒后变成UNKNOWN -
kill -9掉进程后,supervisord 不触发重启 -
supervisorctl restart xxx返回成功,但实际进程没变化
必须禁用程序自身的 daemon 模式
所有被 supervisord 托管的程序,必须运行在 foreground(前台)模式——即不 fork、不重定向 stdout/stderr 到文件、不自行脱离终端。
关键操作项:
Linux AI 服务器 — 将 Linux 服务器转换为本地 AI 推理集群。使用 systemd、NVIDIA CUDA 实现无头 Linux AI,零 GUI 开销。
- Redis:配置文件中设
daemonize no(或启动时加--daemonize no) - Nginx:启动命令改用
nginx -c /etc/nginx/nginx.conf -g "daemon off;" - Python 脚本:确保没调用
os.daemon(),日志输出保持print()或写到sys.stdout - Gunicorn:务必加
--preload --daemon=False(注意是False,不是off)
如果你不确定某程序是否支持前台模式,先查它的 --help 输出,搜索 foreground、daemon、no-daemon 等关键词。
supervisord 配置里几个关键参数不能错
仅靠禁用 daemon 不够,supervisord 自身配置也必须匹配进程行为。以下字段直接影响能否稳定拉起和重启:
-
autostart=true:开机/重载时自动启动(默认 true,但显式写出更安全) -
autorestart=unexpected:推荐值,只在非预期退出(如 crash、信号 kill)时重启;避免设为true,否则正常 exit 也会无限重启 -
startsecs=5:进程启动后需稳定运行满 5 秒才算成功;若程序冷启动慢(如 Django + large DB),应调高 -
startretries=3:启动失败最多重试 3 次,之后标记为FATAL;避免设为 0 导致一次失败就放弃 -
redirect_stderr=true:强制把 stderr 合并进 stdout 日志,否则可能看不到错误信息 -
stdout_logfile=/var/log/myapp.log:必须指定绝对路径,且 supervisord 进程要有写权限(常被忽略)
验证和排错最有效的三步
别依赖 supervisorctl status 一眼判断。真实问题往往藏在日志链路里:
- 看 supervisord 主日志:
tail -f /var/log/supervisor/supervisord.log,重点搜spawned、exited、spawnerr - 看具体 program 的 stdout 日志:
tail -f /var/log/myapp.log,确认程序是否真的打印了启动成功的标志(如ready、listening on) - 手动模拟 supervisord 启动方式:
sudo -u myuser /usr/bin/python3 /path/to/app.py,观察是否卡住、报错或立即退出
特别注意:如果程序依赖环境变量(如 DJANGO_SETTINGS_MODULE),必须在配置中用 environment=KEY="value" 显式声明,source ~/.bashrc 类操作在 supervisord 下完全无效。

















