将Flask/Gunicorn应用配置为systemd服务失败,请求排查指导
你的核心问题出在gunicorn的--daemon参数与systemd的进程管理逻辑冲突,再加上启动命令的小细节问题,导致systemd误判服务状态并触发错误的停止操作。
为什么会出现这个错误?
当你在systemd配置里给gunicorn加上--daemon参数时,gunicorn会启动一个后台子进程,然后主进程直接退出(日志里Child 31817 (gunicorn) died (code=exited, status=0/SUCCESS)就是这个原因)。
systemd的设计逻辑是管理前台运行的进程,它看到主进程退出后,会认为服务已经结束,于是执行ExecStop=/bin/kill -s TERM $MAINPID。但此时$MAINPID已经没有指向任何运行中的gunicorn进程(主进程已退出,子进程的PID没被systemd跟踪),所以kill命令因为缺少PID参数报错,最终导致systemd标记服务为失败状态。
另外你提到的启动方式问题:应该用/usr/bin/python3.4 /usr/bin/gunicorn启动,当前配置直接调用/usr/bin/gunicorn可能会使用系统默认的Python版本,这也需要同步修正。
具体修复步骤
1. 修改systemd服务配置
编辑/etc/systemd/system/api-registry.service,调整ExecStart行:
[Service] # 原配置 # ExecStart=/usr/bin/gunicorn --daemon $OPTIONS registry # 修改后的配置(去掉--daemon,指定Python3.4路径) ExecStart=/usr/bin/python3.4 /usr/bin/gunicorn $OPTIONS registry
2. 保留其他配置的注意点
你的OPTIONS里的--pid、日志参数都可以保留,这些不影响systemd的管理,只是用于手动排查时的辅助文件。
3. 重新加载配置并重启服务
执行以下命令让systemd生效新配置:
sudo systemctl daemon-reload sudo systemctl restart api-registry.service
4. 验证服务状态
查看服务是否正常运行:
systemctl status api-registry.service
此时应该显示active (running)状态,日志里也不会再出现kill命令的用法报错。
关键原理说明
systemd本身会负责将服务进程放到后台运行、监控进程状态、自动重启失败的进程,完全不需要依赖应用自身的daemon化功能。让gunicorn以前台模式运行,systemd才能正确跟踪主进程的PID,确保ExecReload和ExecStop命令正常工作。
内容的提问来源于stack exchange,提问作者nskalis




