add by zhj: 下面是在ubuntu上的一些使用经验
1. 简介
supervisor有两个组件:supervisord和supervisorctl,组成了client/server结构。
supervisord负责读入配置文件,然后supervisord监管的应用程序以supervisord子进程的方式启动,supervisord会自动将应用程序的进程转为守护进程,
这样即使你退出shell也没影响。注意,如果一个进程已经是守护进程了,那用supervisord监控时,会出错。
supervisorctl则负责和supervisord进行沟通,获取运行中的进程信息,包含pid,uptime等信息。supervisorctl既可以通过命令行参数进行控制,又能够
直接进入一个特有的shell,通过这个shell管控进程组。这样,既能够让部分同学准确把握进程状况,又能避免放开shell权限,一举多得。
2. 安装和配置
官网: http://www.supervisord.org/
建议用sudo pip install supervisor来安装,不要用apt-get安装
安装后,用echo_supervisord_conf > ~/supervisord.conf生成配置文件
3. 启动和关闭
启动supervisor: supervisord -c /etc/supervisor/supervisor.conf # 如果不指定配置文件,那自动加载/etc/supervisord.conf
一般会配置成开机自启动,所以需要一个init脚本,参见Running supervisord automatically on startup,下载对应你的操作系统的启动脚本就可以了,
不过,里面的内容可能需要修改,比如supervisord和supervisorctl的路径,pid和log的路径与你supervisord.conf中的pid和log路径要相同
关闭supervisor: sudo kill <supervisord进程id> # kill默然会发送SIGTERM信号,supervisord收到该信号会,会关闭所有子进程,最后关闭自己,这个过程可能需要几秒钟
4. 配置文件
详细的配置参见http://www.cnblogs.com/ajianbeyourself/p/5534737.html
supervisord要求监控的进程不能是守护进程。比如要监控nginx,那你要在nginx配置文件nginx.conf中,设置daemon off
supervisor的配置项有很多,下面是公司dev环境上的celery_beat应用程序的配置项
[program:celery_beat]
command=python manage.py celery beat --loglevel=info --settings=configs.dev
directory=/home/zhj/work/hera/ ; 执行command前,先跳转到directory
autorestart=true ; 当进程关闭后,重启,当然,对于用supervisorctl stop xx关闭的进程,不会重启
redirect_stderr=true ; 重定向程序的标准错误到标准输出 (default false)
startsecs=10 ; 启动后坚持运行多长时间被认为是启动成功了, (def. 1)
stopwaitsecs=30 ; 最长结束等待时间,超过这个时间还没收到子进程的SIGCHLD信号,那就用SIGKILL强制结束子进程 (default 10)
stdout_logfile=/var/log/celery/celery_beat.log
stdout_logfile_maxbytes=50MB
autostart=true ; 当supervisor启动后,也随之启动
5. supervisorctl命令
貌似只有启动supervisor时,用到supervisord命令,其实情况下,用supervisorctl就可以了。
用下面的命令进入supervisor shell, sudo最好加上,不然有可能报错
执行supervisorctl时,配置文件的搜索路径如下
$CWD/supervisord.conf
$CWD/etc/supervisord.conf
/etc/supervisord.conf
zhj@pc:~$ supervisorctl -c /etc/supervisor/supervisord.conf
celery_beat STOPPED Not started
celeryworker_celery: STOPPED Not started
celeryworker_celery: STOPPED Not started
celeryworker_email STOPPED Not started
supervisor> help default commands (type help <topic>):
=====================================
add exit open reload restart start tail
avail fg pid remove shutdown status update
clear maintail quit reread signal stop version supervisor> help start
start <name> Start a process
start <gname>:* Start all processes in a group
start <name> <name> Start multiple processes or groups
start all Start all processes
supervisor>
下面是supervisorctl命令行下的命令:
status #查看supervisord监控的所有进程的状态
celery status #查看celery进程的状态
stop xxx #停止某一个进程(xxx),xxx为[program:theprogramname]里配置的值
start xxx #启动某个进程
restart xxx #重启某个进程
stop groupworker #重启所
stop all #停止全部进程,注:start、有属于名为groupworker这个分组的进程(start,restart同理)restart、stop都不会载入最新的配置文件
reload #重启supervisor
update #根据最新的配置文件,启动新配置或有改动的进程,配置没有改动的进程不会受影响而重启。 当配置文件修改后,要执行这条命令。
#显示用stop停止掉的进程,即使配置文件设置了autorestart=true,用reload或者update都不会自动重启。
用supervisor监控celery和celery beat,配置参数见celery官方文档提供的链接,
http://docs.celeryproject.org/en/latest/tutorials/daemonizing.html#supervisord
6. supervisor的log
在[program:xxx]中,如果设置了numprocs > 1, 那每个进程会使用单独的一个log文件,我们来分析下面的配置。
stdout和stderr文件都是/var/log/celery/celeryworker_celery.log
supervisor会启动两个celeryworker_celery进程(名称分别是celeryworker_celery:0和celeryworker_celery:1),并在启动时创建celeryworker_celery.log
还有celeryworker_celery.log.1 ~ celeryworker_celery.log.5这5个轮转log文件。这两个进程会分别写不同的log文件,不会写到同一个文件,
这是supervisor保证的。celeryworker_celery.log只会被其中一个进程使用,另一个进程会使用celeryworker_celery.log.xx。当celeryworker_celery.log
达到stdout_logfile_maxbytes时,它会被关闭,并重命名为celeryworker_celery.log.1,如果发现celeryworker_celery.log.1已经存在,那就把这
个已存在的celeryworker_celery.log.1重命名为celeryworker_celery.log.2,依次类推。你可以想象有多个水缸并排,在第一个水缸的顶部有一个注水
口,满了之后,将水缸向右推一个位置,即推到第二个水缸的位置,然后在第一个水缸的位置增加一个新水缸,而最右边的那个水缸被挤出队列。一个注水
口就相当于一个进程,当numprocs>1,即多个进程时,就是在numprocs个水缸上面各有一个进水口。在
http://supervisord.org/configuration.html#program-x-section-settings的配置项`stdout_logfile`中提到It is not possible for two processes
to share a single log file (stdout_logfile) when rotation (stdout_logfile_maxbytes) is enabled. This will result in the file being corrupted.
即当设置了log rotate时,supervisor可以保证每个进程使用不同的log文件
[program:celeryworker_celery]
command=python manage.py celery worker -l info -Q celery -c --settings=configs.local_default
directory=/home/workspace/gikoo/
redirect_stderr=true ; 将stderr重定向到stdout
startsecs=
stopwaitsecs=
stdout_logfile=/var/log/celery/celeryworker_celery.log
stdout_logfile_maxbytes=3KB
autostart=false
autorestart=false
numprocs=
process_name=%(process_num)d
stdout_logfile_backups=
7. 遇到的一些问题
不知是什么原因,用supervisor监控celery worker时,有时会出现僵尸进程,每个celery worker都是一个进程池,
每个进程池有一个main process和一组worker process,每个main process都是supervisor的子进程。但使用中
发现,有时会出现一些celery进程的父进程是1号进程,当时没有检查这些进程是main process还是worker process,
猜想是worker process的可能性比较大,原因有可能是supervisor关闭celery时,main process在没有等待worker
process关闭的情况下就关闭了,这样worker process就没了父进程,1号进程就成了他们的父进程。由于任务的获取
都是main process与broker之间进行的,这样的话,那些1号进程下的worker process由于无法与broker通信,所以
也就不会再执行任务了(这块东西待研究)。
原文:http://chenxiaoyu.org/2011/05/31/python-supervisor.html
经常会碰到要写一些守护进程,简单做法放入后台:
shell> nohup python xxx.py &
偶尔这么做还可以接受,如果一堆这样的呢?
当然还有一个问题,就是各种服务,对应的命令或者路径都不太一致,比如Apache、MySQL或者其他自行编译的工具。
如果可以统一管理这些应用,是不是很哈皮?
按照惯例现Google一把,不失所望找到一个神奇的利器。supervisor!
supervisor地址:http://supervisord.org,官方标语就是:一个进程管理工具。
安装:
sudo pip install supervisor
安装好以后,有两个可执行文件和一个配置文件(平台差异,可能路径不一致):
/usr/bin/supervisord -- supervisor服务守护进程
/usr/bin/supervisorctl -- supervisor服务控制程序,比如:status/start/stop/restart/update等
/etc/supervisor/supervisord.conf -- 配置文件,定义服务名称以及接口等等
下面来一个示例,用web.py写一个hello的程序:
import web
urls = ( '/(.*)','hello' )
app = web.application(urls, globals())
class hello:
def GET(self, name):
return 'hello: ' + name if __name__ == '__main__':
app.run()
这个时候可以直接启动这个程序了,下面来配置supervisor,加入管理。修改supervisord.conf,加入如下片段:
[program:hello]
command=python /home/smallfish/hello.py
autorstart=true
stdout_logfile=/home/smallfish/hello.log
上面的意思应该很容易懂,program后面跟服务的名称,command是程序的执行路径,autorstart是表示应用程序随supervisor的启动而启动,stdout_logfile是捕获标准输出。
到这里,基本搞定了,下面就是启动管理:
shell> sudo /etc/init.d/supervisor start -- 启动supervisor服务
shell> sudo supervisorctl status hello -- 获取hello服务的状态,因为是autorstart,这里已经启动了
hello RUNNING pid 1159, uptime :20:32
shell> sudo supervisorctl stop hello -- 停止hello服务
hello: stopped
shell> sudo supervisorctl stop hello -- 再次停止hello,会有错误信息 hello: ERROR (not running)
shell> sudo supervisorctl start hello -- 启动hello服务 hello: started
OK,基本的操作就是类似这个了,仔细看supervisord.conf文件里会发现有一段[unix_http_server]的配置,默认是9001端口,可以输入用户名和密码,主要用于Basic Auth认证用的。
填写一下,然后重启supervisor服务,打开浏览器输入:http://localhost:9001,如图:
sudo supervisorctl shutdown # 关闭supervisord,会同时关闭supervisord监控的所有进程