Linux 进程管理工具 supervisor 简介及使用技巧

codeskyblue · April 04, 2019 · Last by debugtalk replied at September 03, 2019 · 5498 hits
本帖已被设为精华帖!

前言

很久很久以前写的一篇文章,发现依然很有用。在testerhome转发下

背景

经常碰到要跑一些守护进程。平常我的做法是开一个tmux软件或者screen,然后启动软件。如果有其他人问,我则会建议用

nohup your-program &>nohup.log &

这种方式。

可是这种做法毕竟不是长久之计,机器重启或者不小心kill了某个进程,后台运行的这个进程可能就不小心死掉了。
后来开源界的大牛建议我用supervisor。尝试之后,简直是如获至宝。作为一个存在了长达10年多的进程管理软件,他已经相当成熟。到如今我用这个软件已经超过1年了,希望借这篇文章给大家普及下这个超赞的软件。

Supervisor 是一个客户端服务器系统,包含有两个程序

  1. Supervisor的server部分称为supervisord。主要负责管理子进程,响应客户端的命令,log子进程的输出,创建和处理不同的事件
  2. Supervisor的命令行客户端supervisorctl。它可以与不同的supervisord进程进行通信,获取子进程信息,管理子进程

supervisor的官网地址是 http://supervisord.org/ 我的大部分资料也是来自这里。

优点

相比较传统的方式,supervisor用很多好处

简单

通常管理linux进程的时候,一般来说都需要自己编写一个能够实现进程start/stop/restart/reload功能的脚本,然后丢到/etc/init.d/下面。这么做有很多不好的地方,第一我们要编写这个脚本,这就很耗时耗力了。第二,当这个进程挂掉的时候,linux不会自动重启它的,想要自动重启的话,我们还要自己写一个监控重启脚本。而,supervisor则可以完美的解决这些问题。

进程组

supervisor可以对进程组统一管理,也就是说咱们可以把需要管理的进程写到一个组里面,然后我们把这个组作为一个对象进行管理,如启动,停止,重启等等操作。而linux系统则是没有这种功能的,我们想要停止一个进程,只能一个一个的去停止,要么就自己写个脚本去批量停止。

有效性

当supervisor的子进程挂掉的时候,操作系统会直接给supervisor发信号。而其他的一些类似supervisor的工具,则是通过进程的pid文件,来发送信号的,然后定期轮询来重启失败的进程。显然supervisor更加高效。

安装

先从安装说起。

官网建议debain或者ubuntu 使用 apt-get 安装。 请注意,千万不要这么干 软件源的版本是3.0a8,这个版本有个坑爹的bug,stopasgroup这个设置没有用。

正确的安装方法, 安装完后版本应该 >= 3.1

sudo pip install -U supervisor
sudo echo_supervisord_conf > /etc/supervisord.conf

这个配置文件大部分都不用改,有个地方最好还是改下

[include]
files = supervisor-conf.d/*.ini

然后mkdir /etc/supervisor-conf.d, 各个程序的配置都放到这个目录下。这样安排比较合理一些。

弄完后,启动服务端supervisord -c /etc/supervisord.conf。 接着运行sudo supervisorctl status ,如果没有报错,就说明服务端启动正常了。

添加程序

首先需要准备一个配置文件(如hellod.ini)。放到 /etc/supervisor-conf.d/目录下。分号; 后面的是注释

文件的内容要遵循ini配置文件的规范。下面是个例子,这个例子基本上是通用的,需要改的部分只要上面4行

[program:hello]                 
directory=/home/codeskyblue/hello
command=python hello.py
user=codeskyblue
autostart=true
autorestart=true
redirect_stderr=true
stopsignal=TERM
stopasgroup=true

user代表运行的账户,program:hello, 其中hello是这个supervisor中的名字,方便控制。
其中 stopasgroup代表的意思是 如果停止,将其相关的子进程也一起杀掉。

其实不妨写个shell脚本来生成配置文件,更快一些。贴上我写的一个生成配置的脚本。

#!/bin/sh
# gensvconf.sh

NAME=$(basename $PWD)
COMMAND=$@
USER=$(whoami)

cat > supervisor.ini <<EOF
[program:$NAME]
directory=$PWD
command=$COMMAND
user=$USER
autostart=true
autorestart=true
redirect_stderr=true
stopsignal=TERM
stopasgroup=true
EOF

hello.py的内容很简单

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import sys, time
n = 0
while True:
print >>sys.stdout, 'hello: %d' % n
sys.stdout.flush()
n += 1
time.sleep(1.0)

把生成的配置文件,拷贝过去,更新下supervisor的配置就好了。

cp supervisor.ini /etc/supervisor-conf.d/hello.ini
supervisorctl update
supervisorctl status # 查看hello是否正常运行

正常情况下应该会显示

hello                            RUNNING   pid 30096, uptime 0:02:30

还有一些其他的常用命令(这里我默认你用root,所以我省去了sudo)

  1. supervisorctl tail hello 可以查看进程的输出
  2. supervisorctl reread hello 重新加载hello的配置
  3. supervisorctl remove hello 只有在hello停止运行的时候,才可以。这句是将hello从进程守护列表中移除

还有一个技巧,修改一个配置文件/etc/supervisor.conf的一个地方

[unix_http_server]
file=/var/run//supervisor.sock
chmod=0777 ; 原来是chmod=0700

改完之后,sudo supervisorctl reload 重新加载下配置。 这时在非root用户下,也可以自由的使用supervisorctl了

HTTP 服务

加入如下两行到/etc/supervisord.conf

[inet_http_server]
port = :9001

supervisorctl reload 重新加载配置。打开浏览器输入 http://localhost:9001, 应该就会看到这个页面了,网页上的功能也很全。

supervisor-http

感谢

感谢爸爸,感谢妈妈。感谢开源社区,感谢我的水杯,感谢我那便宜但又好用的键盘。

部分参考了: http://lixcto.blog.51cto.com/4834175/1539136

如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
共收到 17 条回复 时间 点赞

总感觉好像是在提醒我们:server2 部署在服务器可以尝试使用一下😁

现在有systemd了

不感谢老婆?要命

AppetizerIO 回复

以前写的,当时还没有老婆

现在还有人用这东西么? 不是都用systemd了么

我linux菜,这种有掌握的必要性吧

孙高飞 回复

就易用性而言,system的还是比不过 supervisor的

这个用再部署Python Web项目的时候用到过;
文章写得很详细,指的学习借鉴。

谢谢啦

—— 来自TesterHome官方 安卓客户端

codeskyblue 回复

简单不代表就好。。。。。如果真的好, 不会基本所有liunx发行版本都用systemd作为默认选项了

孙高飞 回复

不作为linux的默认进程管理工具确实是有原因的,比如supervisor不支持 启动顺序,另外依赖Python2.7。 而systemd虽然易用性不怎么地,但是鲁棒

codeskyblue 回复

supervisor依赖python,python2.7或以上都支持,版本和实际守护的py进程版本没关系

geons 回复

No, 你试过之后就知道了。python3并不支持

codeskyblue 回复

现在应该已经支持python3了http://supervisord.org/changes.html
去年还没发布时在github上下载应急用过

思寒_seveniruby 将本帖设为了精华贴 20 Apr 20:34

看起来不错,回头用用看。

好文,收藏学习一下;

遇到了问题被坑了好久,也发在这里分享下:

cat >> $SUPERVISOR_HOME/supervisord.conf <<EOF
[program:$NAME]
directory=$PWD
command=$PYTHON_VENV_HOME/bin/python "$TASK_WORKER_MAIN"
user=$USER
autostart=true
autorestart=true
redirect_stderr=true
stopsignal=TERM
stopasgroup=true
EOF

directory 这一项中,务必不能加引号,即使在路径中包含空格也不能加:

directory="$PWD"

否则,会报如下错误信息:

exited: task-worker (exit status 127; not expected)
supervisor: couldn't chdir to "/Users/debugtalk/task-worker": ENOENT
supervisor: child process was not spawned
需要 Sign In 后方可回复, 如果你还没有账号请点击这里 Sign Up