在服务器上部署的应用,经常需要有,
- 随系统自动启动的能力;
- 意外崩溃/退出后自行恢复运行的能力;
- 便于查看运行状况,以及统一管理的能力。
当然还有其他需求,不过事实上上述的前两条最为基本。Supervisor 是 Python 开发的一个运行于 *nix 系统下的 C/S 结构的管理服务工具。它拥有不止于上述要求的能力。它的 Client 程序为 supervisorctl
,长时间运行于后台的守护程序则是 supervisord
,后者甚至内置了一个可以连接的 Web Server 供查看服务状况。
superviserd
启动时,可以指定一个配置文件,命令行开关为 -c
加配置文件名。如果没有显示指定,则按下列顺序寻找:
1 2 3 4 5 6 |
$CWD/supervisord.conf $CWD/etc/supervisord.conf /etc/supervisord.conf /etc/supervisor/supervisord.conf (Supervisor 3.3.0 起) ../etc/supervisord.conf (相对于可执行文件) ../supervisord.conf (相对于可执行文件) |
运行起来以后,可以使用
supervisorctl
来查看/控制,状态查看(status all
其实可省略):
1 |
supervisorctl status all |
全部停止:
1 |
supervisorctl stop all |
全部启动:
1 |
supervisorctl start all |
Web 相关的设置如下:
1 2 3 4 |
[inet_http_server] ; 缺省是关闭的 port=0.0.0.0:9001 ; 指定监听的 IP 地址和端口,*:port 为所有接口 username=user ; 缺省为无需用户名 password=123456 ; 缺省为无需密码 |
设置需改后,要记得重新加载以生效(切记!):
1 |
supervisorctl reload |
从最佳实践的角度出发,各个需要监控管理的程序最好各自有自己的专属配置,并将之
include
到主配置文件中,这是 *nix 下的常规操作,不赘述。一个程序的配置文件样例如下(仅供参考,不作详解):
1 2 3 4 5 6 7 8 9 |
[program:mindoc] process_name=mindoc command=/srv/app/mindoc/mindoc directory=/srv/app/mindoc autostart=true autorestart=true user=someone numprocs=1 redirect_stderr=true |
自带的
echo_supervisord_conf
命令可以输出非常完整且有详细解释的样例配置文件,可以自行查看。
最后一个问题是,别的程序都被 supervisor
管理了,那它自己呢?显然不能揪着自己的头发把自己拽离地面。鉴于 CentOS 作为服务器过于普遍,以其为示例说明开机启动 Supervisor 服务。
首先, vim /lib/systemd/system/supervisord.service 来创建 Supervisor 的系统服务,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
# supervisord service for systemd (CentOS 7.0+) [Unit] Description=Supervisor daemon [Service] Type=forking ExecStart=/usr/bin/supervisord -c /etc/supervisor/supervisord.conf ExecStop=/usr/bin/supervisorctl $OPTIONS shutdown ExecReload=/usr/bin/supervisorctl $OPTIONS reload KillMode=process Restart=on-failure RestartSec=42s [Install] WantedBy=multi-user.target |
将服务启用:
1 |
systemctl enable supervisord.service |
启动:
1 |
systemctl start supervisord.service |
停止:
1 |
systemctl stop supervisord.service |
最后,把网上一个小朋友的教训引用过来(虽然 1. 他的叙述很乱,我还略微做了加工;2. 如果按照上文的说明进行配置和操作不应该出现此问题):
确保通过 supervisor 运行的进程只有一个!是的,切记。比如你的操作不是那么的规范:你先通过 supervisord -c /etc/supervisor/supervisord.conf
将
supervisor 启动了,几天后忘记了之前已启动,当通过 supervisorctl status
去看运行状态时,会看到提示
unix:///tmp/supervisor.sock no such file,你就可能会想是不是 supervisord
挂掉了?不管那么多了,先启动吧,于是做了个操作
supervisord。之后看起来服务都正常了,于是干其他事情去了。可能不久就会收到同事的反馈:数据不正常!你忙了一个小时,各种打日志,各种看代码,最终结果却是:有两个进程在跑同一个执行文件!你会发现一个是当前 supervisor 管理的进程,另一个进程的 ppid 和 supervisor 的 pid 不一样!于是你明白了:supervisord 的操作没有杀死旧进程,而是又启动了一个新进程,两个进程同时运行,结果导致你的数据异常。最终你先将旧进程的父进程杀掉,再杀掉旧进程,再 reload supervisor,之后终于恢复正常。从这一波的操作可以看出:
1. 当看到 unix:///tmp/supervisor.sock no such file 时,一定要好好排查,不要着急去启动。即:遇到问题,不要想着重启!
2. 可以使用一些更优雅的方式来运行 supervisor。比如系统是 CentOS,你把 supervisor 做成一个 systemctl 服务就能避免这些问题。
3. reload supervisor 之后,一定记得检查下,是不是只有一个进程在跑!
此案例原始文章在 https://blog.csdn.net/u012375924/article/details/84946987。
另外,之前一直看有人说 Supervisor 不支持 Python 3,刚才去官网查看更新记录,可以看到从版本 4.0 开始,Supervisor 已经开始支持 Python 3(最低版本要求 3.4)。