Ubuntu下的Supervisor一键安装脚本

之前记录过一篇Supervisor的文章:https://laoyur.com/archives/803/
然而那篇文章其实是引用的『淡水网志』哥的一篇博文:https://www.restran.net/2015/10/04/supervisord-tutorial/,那篇博文对Supervisor写得比较详细,推荐大家阅读。

不过有个痛点还是没解决,每次实践Supervisor的安装和配置,都比较痛苦,像我这种记性较差的人,每次都要找到那篇文章按部就班来操作,少说得花个10分钟。

痛定思痛,决定花几个10分钟来弄个一键配置脚本(仅适用于Ubuntu),以省去以后更多的10分钟。

一键配置脚本

sudo pip install supervisor  # 这条没放到一键脚本中,需要你自己安装supervisor,推荐用pip,而且建议加sudo,不然可能会被装到`~/.local/bin/`下。
sudo su -c "wget https://laoyur.com/dl/blog/2016/supervisor-setup.sh -O- | bash"

接下来如何使用

cd /etc/supervisord  # 在这里存放你的各Program的配置文件
cp program-sample-ini myapp.ini  # 配置文件必须是ini后缀

然后编辑myapp.ini,内容如下:

[program:program_name]
directory=/ ; 执行 command 之前,会先cd到该工作目录
command=python your_py_file  ;注意,如果executable使用相对路径,则它是从$PATH中寻找的,并不会从上面定义的directory中寻找。所以推荐用绝对路径。
user=username                 ; 使用哪个用户来启动该进程
stdout_logfile=log_file_path  ; 使用绝对路径。NONE表示不输出
;以下为可选内容
;numprocs=1                 ; 默认为1
;process_name=%(program_name)s   ; 默认为 %(program_name)s,即 [program:x] 中的 x
autorestart=true            ; 程序崩溃时自动重启,重启次数是有限制的,默认为3次
redirect_stderr=true        ; 将stderr重定向到stdout_logfile
loglevel=info
stopasgroup=true
killasgroup=true

一般情况,你仅需要编辑前五行:

  • 首行是你的Program名称,把your_program_name换成你自己的;
  • directory是工作目录,要不要切换看你自己具体情况;
  • command是你要执行的命令,我在Supervisor的init.d脚本中为$PATH加了/user/local/bin,所以这里python不用写全路径,如果你要执行的命令有自己独特的search path,可以在命令前加上env PATH="your_special_path:%(ENV_PATH)s"。一般情况,推荐这里使用绝对路径,千万不要想当然地认为写相对路径的话,就会从directory中寻找。关于这个问题,可以看看这个链接:https://github.com/Supervisor/supervisor/pull/648 ,然而时至今日,该PR还没有被批准合并 🙁 ;
  • user是你希望以什么用户身份执行command;
  • stdout_logfile将你程序的stdout记录到文件,NONE表示不输出到文件,跟/dev/null类似。注意这个路径并不是相对于directory的,需要使用绝对路径。

Updated:2016-09-21
默认.ini中新增了两个配置:

stopasgroup=true
killasgroup=true

加上这两个选项可以防止supervisorctl stop some_program无法将program的child process结束的情况发生。
举个例子,用supervisor运行celery worker,如果不将killasgroup设为true,那supervisorctl stop时,celery的进程将没办法被杀光,总是会留下一个。该问题可以参考这个链接:http://stackoverflow.com/questions/31800447/make-supervisor-really-stop-celery-workers


一般出错的话,问题常常出在command的$PATH上。比如你要用Supervisor跑一个virtualenv中的gunicorn,要么写上这个gunicorn的full path,要么像上面说的一样,在command中指定env PATH。
举个例子:

  • 先通过pyenv which python,找到所属virtualenv的bin目录,比如/root/.pyenv/versions/env2712/bin
  • 把bin目录添加到PATH中,于是command应该这么写:env PATH="/root/.pyenv/versions/env2712/bin:%(ENV_PATH)s" gunicorn -c your_conf.py yourproj.wsgi

好了,编辑好这个ini文件后,来测试一下Supervisor到底能不能工作,启动supervisord:

sudo service supervisord start

然后确认一下服务状态(Ubuntu 14.04不适用):

sudo service supervisord status

正常情况会显示Active: active (running)字样

如果有问题,去看一下log报什么错:

tail /var/log/supervisord.log

如果一切OK的话,再测试一下重启:

sudo reboot -f

再然后

以上都通过,说明一键配置脚本工作正常,再往后的操作,就得跟supervisorctl打交道了。
如果需要新增Program,就重复上面的步骤添加ini文件,然后用sudo supervisorctl update来重新加载配置。
关于supervisorctl的更多操作,这里不再赘述,自己通过supervisorctl help来查看吧。

如何卸载

sudo service supervisord stop  # 停止服务先
sudo update-rc.d -f supervisord remove  # 禁用脚本自启动
sudo rm -f /etc/init.d/supervisord  # 删除init脚本
sudo rm -f /etc/supervisord.conf  # 删除supervisord配置文件
sudo rm -fr /etc/supervisord/  # 删除你所有的程序配置文件,请三思而后行
sudo rm -f /ver/log/supervisord.log  # 删除supervisord的log文件
pip uninstall supervisor  # 删除Supervisor,但真的要这么绝吗?

Supervisorctl 常用命令

supervisorctl有四个命令最令人疑惑:
reread/reload/restart/update,官方文档中似乎没有覆盖到,因此不少人抱怨,比如这个issue:
https://github.com/Supervisor/supervisor/issues/720

supervisorctl help里对这四个命令的解释如下:
reread: Reload the daemon's configuration files
reload: Restart the remote supervisord
restart:

restart <name>      Restart a process
restart <gname>:*   Restart all processes in a group
restart <name> <name>   Restart multiple processes or groups
restart all     Restart all processes

Note: restart does not reread config files. For that, see reread and update.

update:

update          Reload config and add/remove as necessary
update all      Reload config and add/remove as necessary
update <gname> [...]    Update specific groups

大致总结如下:

supervisorctl reread,重新载入各配置文件,之后就可以做add/remove等操作;
supervisorctl update,先reread,再来更新各Program,新增的自动start;删除掉的自动stop;发生修改的自动重启;
supervisorctl reload,此操作会重新载入各配置文件并重启Supervisord,当然也会重启各Program;
supervisorctl restart,仅重启各Program,然而如果Program对应的配置文件发生了更改,并不会应用新配置。

总结一下最常见的使用case:
– 启用/禁用某个Program:add/remove,被禁用的Program即使reload后也还是处于禁用状态
– 修改过了配置后重新应用:update。貌似update跟update all没有区别?// FIXME
– 未修改配置时重启Program:restart
– 不管有没有修改过配置,全部重启:reload

Ubuntu下的Supervisor一键安装脚本》有4个想法

发表评论

电子邮件地址不会被公开。 必填项已用*标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据