service的替代:Supervisor——配置和坑
对于一个想要长期在后台跑的服务,比如一个 web server,一般有这几种方法:
- 使用 nohup + &
- 做成一个 service,使用
sudo service <servicename> <command>控制 - 自行实现 daemon
- 利用 screen 软件,放到一个 screen 里面跑
第一个方法实用性太差;第二个和第三个在能处理好日志时不错,但是其维护起来较为麻烦;最后一个方法是笔者以前常用的方法。
supervisor 是用 python 编写的程序,其能够将非 daemon 程序放到后台运行并监控,还能做到检测到程序挂掉时重新拉起。它使用了 client/server 架构,因此提供了 web UI 以便远程控制(其实有坑)。

安装
Ubuntu: sudo pip install supervisor
(不建议使用 apt 安装)
配置
安装完成后建立配置文件夹,按照惯例我们放到 /etc/supervisor 路径下。
1 | # 将默认设置导入路径 |
下面编辑配置:vim /etc/supervisor/supervisord.conf
大部分配置都不需要改,直接将最后的一行改一下:
1 | [include] |
对于想要交由 supervisor 托管的程序,在 /etc/supervisor/conf.d 路径下建立文件即可,如
1 | [program:webserver] |
配置完成后,启动 supervisor 的 server 端:
sudo supervisord -c /etc/supervisor/supervisor.conf
supervisor 提供了两种方式进行控制:
- 命令行式,使用
sudo supervisorctl进入交互模式,也可后跟 command,如:sudo supervisorctl status/start/stop/reload/update - Web UI,在坑的部分讲
需要注意的是,supervisor 只支持非 daemon 的程序,也就是说假如你想托管本身就支持 daemon 模式的程序(如 docker),你需要去除运行时的 -d 参数。
坑
下面介绍一下 supervisor 的坑。
它提供了一个 web UI,支持 unix socket 和 http 两种方式。开放之前,先修改一下用户名和密码(*_http_server.username/password 字段)。注意这里有个坑,要同步改一下下面的 supervisorctl.username/password 字段,否则每次 supervisorctl 都要输密码。
(吐槽:明文/裸hash 保存密码……)
改完密码 nginx 直接配置:
1 | location / { |
配置完一刷新,网关错误,一查log,发现自动建立的文件是 root|root 700的,nginx 没有 socket 的访问权限。进配置文件把权限改成 777,刷新,终于出来了界面。
点一下界面的 refresh 按钮,发现请求被 301 重定向到 http 了……而且是在 header 里面写死了协议,完全忽略了我们传入的 proto 字段。这个问题我翻阅了其文档也没有找到解决方法,最后在 GitHub 发现很多人也遇到这个问题,提出了很多 issue 和 PR,但是不知道为什么,开发者到现在也不愿意解决这个问题。
最后的结果是,这个所谓的 web UI 实际上只能拿来看,并不能实际控制后台的程序……至少,不能安全地在 https 下使用。