概述
项目中遇到有些脚本需要通过后台进程运行,保证不被异常中断,除了通过 nohup、&、screen 以外,更推荐的方法就是用 Supervisor。
Supervisor 是用 Python 开发的一套通用的进程管理程序,能将一个普通的命令行进程变为后台 daemon,并监控进程状态,异常退出时能自动重启。它是通过 fork/exec 的方式把这些被管理的进程当作 supervisor 的子进程来启动,这样只要在 supervisor 的配置文件中,把要管理的进程的可执行文件的路径写进去即可。也实现当子进程挂掉的时候,父进程可以准确获取子进程挂掉的信息的,可以选择是否自己启动和报警。supervisor 还提供了一个功能,可以为 supervisord 或者每个子进程,设置一个非 root 的 user,这个 user 就可以管理它对应的进程。
安装
1:easy_install 安装:easy_install supervisor
2:pip 安装:pip install supervisor
3:Debian / Ubuntu 可以直接通过 apt 安装:apt-get install supervisor
配置
- 通过 apt-get install 安装后,supervisor 的配置文件在:
/etc/supervisor/supervisord.conf
supervisor 的配置文件默认是不全的,不过在大部分默认的情况下,上面说的基本功能已经满足。而其管理的子进程配置文件在:
/etc/supervisor/conf.d/*.conf
- 通过 easy_install 或者 pip 安装的,配置文件不存在,需要自己导入。
运行 echo_supervisord_conf 打印出一个配置文件的样本,样本说明可以看 supervisor(一)基础篇的详细说明,要是设置样本为一个配置文件则:
1:运行 echo_supervisord_conf,查看配置样本:echo_supervisord_conf
2:创建配置文件:echo_supervisord_conf > /etc/supervisord.conf
配置子进程配置文件,可以直接在 supervisor 中的 [program:theprogramname] 里设置。
;[program:theprogramname] ; 这个就是咱们要管理的子进程了,":" 后面的是名字,最好别乱写和实际进程
有点关联最好。这样的 program 我们可以设置一个或多个,一个 program 就是
要被管理的一个进程
;command=/bin/cat ; 这个就是我们的要启动进程的命令路径了,可以带参数
例子:/home/test.py -a 'hehe'
有一点需要注意的是,我们的 command 只能是那种在终端运行的进程,不能是
守护进程。这个想想也知道了,比如说 command=service httpd start。httpd 这个进程被 linux 的 service 管理了,我们的 supervisor 再去启动这个命令
这已经不是严格意义的子进程了。这个是个必须设置的项
;process_name=%(program_name)s ; 这个是进程名,如果我们下面的 numprocs 参数为 1 的话,就不用管这个参数
了,它默认值 %(program_name)s 也就是上面的那个 program 冒号后面的名字,但是如果 numprocs 为多个的话,那就不能这么干了。想想也知道,不可能每个
进程都用同一个进程名吧。;numprocs=1 ; 启动进程的数目。当不为 1 时,就是进程池的概念,注意 process_name 的设置
默认为 1。。非必须设置
;directory=/tmp ; 进程运行前,会前切换到这个目录
默认不设置。。。非必须设置
;umask=022 ; 进程掩码,默认 none,非必须
;priority=999 ; 子进程启动关闭优先级,优先级低的,最先启动,关闭的时候最后关闭
默认值为 999。。非必须设置
;autostart=true ; 如果是 true 的话,子进程将在 supervisord 启动后被自动启动
默认就是 true。。非必须设置
;autorestart=unexpected ; 这个是设置子进程挂掉后自动重启的情况,有三个选项,false,unexpected
和 true。如果为 false 的时候,无论什么情况下,都不会被重新启动,如果为 unexpected,只有当进程的退出码不在下面的 exitcodes 里面定义的退
出码的时候,才会被自动重启。当为 true 的时候,只要子进程挂掉,将会被无
条件的重启
;startsecs=1 ; 这个选项是子进程启动多少秒之后,此时状态如果是 running,则我们认为启
动成功了
默认值为 1。。非必须设置
;startretries=3 ; 当进程启动失败后,最大尝试启动的次数。。当超过 3 次后,supervisor 将把
此进程的状态置为 FAIL
默认值为 3。。非必须设置
;exitcodes=0,2 ; 注意和上面的的 autorestart=unexpected 对应。。exitcodes 里面的定义的
退出码是 expected 的。;stopsignal=QUIT ; 进程停止信号,可以为 TERM, HUP, INT, QUIT, KILL, USR1, or USR2 等信号
默认为 TERM。。当用设定的信号去干掉进程,退出码会被认为是 expected
非必须设置
;stopwaitsecs=10 ; 这个是当我们向子进程发送 stopsignal 信号后,到系统返回信息
给 supervisord,所等待的最大时间。超过这个时间,supervisord 会向该
子进程发送一个强制 kill 的信号。默认为 10 秒。。非必须设置
;stopasgroup=false ; 这个东西主要用于,supervisord 管理的子进程,这个子进程本身还有
子进程。那么我们如果仅仅干掉 supervisord 的子进程的话,子进程的子进程
有可能会变成孤儿进程。所以咱们可以设置可个选项,把整个该子进程的
整个进程组都干掉。设置为 true 的话,一般 killasgroup 也会被设置为 true。需要注意的是,该选项发送的是 stop 信号
默认为 false。。非必须设置。。;killasgroup=false ; 这个和上面的 stopasgroup 类似,不过发送的是 kill 信号
;user=chrism ; 如果 supervisord 是 root 启动,我们在这里设置这个非 root 用户,可以用来
管理该 program
默认不设置。。。非必须设置项
;redirect_stderr=true ; 如果为 true,则 stderr 的日志会被写入 stdout 日志文件中
默认为 false,非必须设置
;stdout_logfile=/a/path ; 子进程的 stdout 的日志路径,可以指定路径,AUTO,none 等三个选项。设置为 none 的话,将没有日志产生。设置为 AUTO 的话,将随机找一个地方
生成日志文件,而且当 supervisord 重新启动的时候,以前的日志文件会被
清空。当 redirect_stderr=true 的时候,sterr 也会写进这个日志文件
;stdout_logfile_maxbytes=1MB ; 日志文件最大大小,和 [supervisord] 中定义的一样。默认为 50
;stdout_logfile_backups=10 ; 和 [supervisord] 定义的一样。默认 10
;stdout_capture_maxbytes=1MB ; 这个东西是设定 capture 管道的大小,当值不为 0 的时候,子进程可以从 stdout
发送信息,而 supervisor 可以根据信息,发送相应的 event。默认为 0,为 0 的时候表达关闭管道。。。非必须项
;stdout_events_enabled=false ; 当设置为 ture 的时候,当子进程由 stdout 向文件描述符中写日志的时候,将
触发 supervisord 发送 PROCESS_LOG_STDOUT 类型的 event
默认为 false。。。非必须设置
;stderr_logfile=/a/path ; 这个东西是设置 stderr 写的日志路径,当 redirect_stderr=true。这个就不用
设置了,设置了也是白搭。因为它会被写入 stdout_logfile 的同一个文件中
默认为 AUTO,也就是随便找个地存,supervisord 重启被清空。。非必须设置
;stderr_logfile_maxbytes=1MB ; 这个出现好几次了,就不重复了
;stderr_logfile_backups=10 ; 这个也是
;stderr_capture_maxbytes=1MB ; 这个一样,和 stdout_capture 一样。默认为 0,关闭状态
;stderr_events_enabled=false ; 这个也是一样,默认为 false
;environment=A="1",B="2" ; 这个是该子进程的环境变量,和别的子进程是不共享的
;serverurl=AUTO ;
配置参考
/etc/supervisor/conf.d/test.conf
# 项目名
[program:blog]
# 脚本目录
directory=/opt/bin
#脚本执行命令
command=/usr/bin/python /opt/bin/test.py
#supervisor 启动的时候是否随着同时启动,默认 True
autostart=true
#当程序 exit 的时候,这个 program 不会自动重启, 默认 unexpected
#设置子进程挂掉后自动重启的情况,有三个选项,false,unexpected 和 true。如果为 false 的时候,无论什么情况下,都不会被重新启动,如果为 unexpected,只有当进程的退出码不在下面的 exitcodes 里面定义的
autorestart=false
#这个选项是子进程启动多少秒之后,此时状态如果是 running,则我们认为启动成功了。默认值为 1
startsecs=1
#日志输出
stderr_logfile=/tmp/blog_stderr.log
stdout_logfile=/tmp/blog_stdout.log
#脚本运行的用户身份
user = zhoujy
#把 stderr 重定向到 stdout,默认 false
redirect_stderr = true
#stdout 日志文件大小,默认 50MB
stdout_logfile_maxbytes = 20M
#stdout 日志文件备份数
stdout_logfile_backups = 20
[program:easyswoole]
directory=/home/wwwroot/easyswoole
command=php easyswoole start
autorestart=true
startsecs=1
stderr_logfile=/tmp/supervisord_easyswoole.log
stdout_logfile=/tmp/supervisord_easyswoole.log
user = root
redirect_stderr = true
stdout_logfile_maxbytes = 20M
stdout_logfile_backups = 20
# 以下两个要加,否则会报.ini file does not include supervisord section
[supervisord]
[supervisorctl]
使用
运行
1)apt-get install 安装的 supervisor 直接可以通过 /etc/init.d/supervisor 运行:
/etc/init.d/supervisor start
2)通过 easy_install 安装的 supervisor 运行 supervisord 运行:
# 注意,要守护的进程不要单独启动,直接执行 supervisor 即可
supervisord -c /etc/supervisord.conf
编辑配置后,可以通过 supervisorctl update 生效
web 界面
[inet_http_server]
port=0.0.0.0:9002
username=user
password=123
子进程管理
# 有多少子进程
supervisorctl status
# easyswoole 进程
supervisorctl stop easyswoole
supervisorctl start easyswoole
# 全部
supervisorctl stop all
supervisorctl start all
参考资料
Supervisor 官方文档
Supervisor(一)基础篇
Supervisor(二)eventevent”)
Supervisor(三)xml_rpcxml_rpc”)