不少朋友都是用 Flask 框架来写小服务器的,方便又快捷,还能一键运行,很舒服。不过,如果你真的想把你的服务部署到服务器上,那你就会发现其实还有一些功课要做,这篇文章里,我们主要来谈谈如何将写好的程序在服务器上变成一个服务而不是终端里执行的命令。
如果我们用 Python 写了一个网站应用,那么它就需要一直运行来监听 HTTP 请求,如果在终端直接执行
python main.py
那就太麻烦了,你还得一直保持终端开启,端了 ssh,程序也就结束了。
起初,我是这么做的:
nohup python -u /home/logcg/main.py > /home/logcg/out.log 2>&1 &
,Nohup 这个工具能让程序在后台运行,这样即使你断开了 ssh,关闭了终端,服务器上的程序依旧在运行,如果你把这条命令写到
rc.local
,那么它就能每次跟随服务器启动而启动,完美……吗?
这个解决方案看上去很完美,类似的还有比如 screen 等命令,但仔细一想,如果程序实行意外崩溃了怎么办?
——很遗憾,没办法,唯一的办法就是等你的客户告诉你:你的网站打不开了。
总之,现在我们可以用另一个工具直接将你的程序“变成”系统级服务,就像 Nginx,像 fail2ban 那样,一旦程序崩溃,系统会负责将它重启——除非你手动停止它。
Supervisor
这是一个纯 Python 实现的工具,它是一个轻量级进程管理工具,能够根据你的配置自动启动并监控进程,一旦程序意外崩溃,它就会重新启动它们。
1 2 |
apt install supervisor service supervisor restart |
启动后,在
/etc/supervisor/conf.d
目录下写入你的命令相关配置,最好是一个命令一个文件,方便管理,文件名要求是
.conf
后缀。
比如,我有一个这样的服务:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
[program:logcg] command=gunicorn wsgi:app -c gunicorn.config.py ; 被监控的进程路径 directory=/home/logcg/ ; 执行前要不要先cd到目录$ autostart=true ; 随着supervisord的启动而启动 autorestart=true ; 自动重启。。当然要选上了 startretries=10 ; 启动失败时的最多重试次数 exitcodes=0 ; 正常退出代码 stopsignal=TERM ; 用来杀死进程的信号 默认 TERM,支持 gunicorn graceful restart stopwaitsecs=10 ; 发送SIGKILL前的等待时间 redirect_stderr=true ; 重定向stderr到stdout ; 默认为 false,如果设置为 true,当进程收到 stop 信号时,会自动将该信号发给该进$ stopasgroup=false ; send stop signal to the UNIX process ; 默认为 false,如果设置为 true,当进程收到 kill 信号时,会自动将该信号发给该进$ killasgroup=false ; SIGKILL the UNIX process group (def false) |
这样,我的 Python 程序就变成了一个叫做“logcg”的服务。
最后,
supervisorctl update all
更新所有服务的配置信息:
1 2 |
➜ supervisor supervisorctl update all logcg: added process group |
当然,你还可以使用命令
supervisorctl status all
来查看所有服务的运行状态,将
all
换成特定的服务名称,就能查询单个的服务了。
这下,再也不用担心因为一些意外的小问题导致程序崩溃再也起不来了。
报错
unix:///var/run/supervisor.sock no such file
如果你在更新软件包后不幸遇到了这个错误,那你不是一个人,https://github.com/Supervisor/supervisor/issues/480 当然,
上面这个问题在新版的 Supervisor 中得到了解决,但如果你是持续更新的,那这个问题可能并不能自动修复,解决办法是——重装。
直接使用命令
apt remove supervisor
然后
apt remove supervisor
就可以了,原因是启动脚本使用的路径是
/usr/bin/supervisord
而我们实际命令路径是
/usr/local/bin/supervisord
,而你更新时并不会重建服务信息,于是它始终从错误的路径启动服务,于是服务启动失败,自然就报错
unix:///var/run/supervisor.sock no such file
了。
我们也有对应的解决办法:
1 2 |
<del>touch /var/run/supervisor.sock supervisord -c /etc/supervisor/supervisord.conf</del> |
如果你是按照本文进行配置的,那只需要复制粘贴执行这两条语句就好了,第一句是手动创建这个.sock文件,以供 supervisor 读取,第二句是让 supervisord 以默认配置进行启动一下,然后就可以正常使用了。
参考文献
本文由 落格博客 原创撰写:落格博客 » 使用 Supervisor 将你的 Python 程序变成服务
转载请保留出处和原文链接:https://www.logcg.com/archives/3304.html
博主说的好,我选择systemd🐒🐒
不行不行,还得写脚本加进去……不会啊