使用Supervisor保护进程不死不灭
概要
-
Supervisor
是用Python
开发的一套通用的进程管理程序,能将一个普通的命令行进程变为后台daemon
,并监控进程状态,异常退出时能自动重启。 - 可以选择是否自己启动和报警。
supervisor
还提供了一个功能,可以为supervisord
或者每个子进程,设置一个非root
的user
,这个user
就可以管理它对应的进程。 - 后期不定期更新及优化中~~~
Supervisor
已经过测试,可以在Linux
(Ubuntu 9.10),Mac OS X
(10.4 / 10.5 / 10.6)和Solaris
(10 for Intel)和FreeBSD 6.1
上运行。它可能在大多数UNIX
系统上都能正常工作。在任何版本的
Windows
下,Supervisor
都不会运行。众所周知,
Supervisor
可以使用Python 2.4
或更高版本,但不能在任何版本的Python3
下使用。安装 安装Supervisor
本人使用的是
Centos7
,7.3和7.5版本都测试了没有问题,下面开始安装:yum -y install epel-release
yum install python-pip -y文章末尾有详细说明pip的加速方法,建议先进行pip加速再使用pip。
pip install supervisor
如何pip安装不成功,还可以使用
easy_install
来安装supervisor
yum -y install python-setuptools
easy_install supervisor
查看是否安装成功
supervisord -v
创建文件保存的目录
mkdir /usr/local/supervisor
mkdir /var/log/supervisor
mkdir /etc/supervisor.d
开始编辑
supervisord
的配置文件首先生成配置文件
echo_supervisord_conf > /etc/supervisord.conf
vim /etc/supervisord.conf
分别找到含有
/tmp/
的语句,并修改我们上一步创建的三个目录(若担心配置文件改错了,将原代码注释,自己重新写一行也行);
这里配置是否用unix socket通信来让supervisor与supervisorctl做通信
;
file=/tmp/supervisor.sock;
UNIX socket 文件,supervisorctl 会使用
;
修改为刚刚创建的目录 /usr/local/supervisor 目录,避免被系统删除
file=/usr/local/supervisor/supervisor.sock
;
chmod=0700;
socket 文件的 mode,默认是 0700
;
chown=nobody:nogroupsocket 文件的 owner,格式: uid:gid
;
username=user;
supervisorctl与supervisorctl通信的账户密码
;
password=123 ;
如果需要使用web界面去控制守护状态的话,就把下面四行的;
去掉
[inet_http_server];
HTTP 服务器,提供 web 管理界面
;
这里是用的http的方式做通信
port=0.0.0.0:9001;
Web 管理后台运行的 IP 和端口,如果开放到公网,需要注意安全性
username=user;
登录管理后台的用户名
password=123;
登录管理后台的密码
... ...[supervisord]
;
logfile=/tmp/supervisord.log ;
日志文件,默认是 logfile=/tmp/supervisord.log
;
修改为 /var/log 目录,避免被系统删除
logfile=/var/log/supervisor/supervisord.log ;
;
日志文件多大时进行分割
logfile_maxbytes=50MB;
日志文件大小,超出会 rotate,默认 50MB
;
最多保留多少份日志文件
logfile_backups=10;
日志文件保留备份数量默认 10
loglevel=info;
日志级别,默认 info,其它: debug,warn,trace
;
pidfile=/tmp/supervisord.pid ;
pid 文件
;
修改为 /usr/local/supervisor 目录,避免被系统删除
pidfile=/usr/local/supervisor/supervisord.pid ;
;
设置启动supervisord的用户,一般情况下不要轻易用root用户来启动,除非你真的确定要这么做
user=root;
(default is current user, required if root)
... ...[rpcinterface:supervisor]
supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface
... ...[supervisorctl]
;
这里选择supervisorctl到底用以上两种中的哪种方式来与supervisor通信,选择一种即可,记得填写密码
;
必须和'unix_http_server'里面的设定匹配
;
serverurl=unix:///tmp/supervisor.sock ;
use a unix:// URLfor a unix socket
;
修改为 /usr/local/supervisor 目录,避免被系统删除
serverurl=unix:///usr/local/supervisor/supervisor.sock ;
use a unix:// URLfor a unix socket
;
serverurl=http://127.0.0.1:9001 ;
use an http:// url to specify an inet socket
;
username=chris;
should be same as http_username if set
;
password=123;
should be same as http_password if set
将该文件的最后一行
[include]
前面的分号去掉,并且在下面添加一行:[include]
;
files = relative/directory/*.ini
files = /etc/supervisor.d/*.conf
我们以后监控相应进程的配置文件都会放在这个
/etc/supervisor.d/
中,所以这里要将[include]
功能打开(即去掉分号),现在可以保存并退出这个文件了。至此,supervisor已经可以正常运行了。
创建实例进程
此时重新开一个终端,我们创建一个能够一直存在的进程(路径和进程名随便指定,只要不跟系统文件重名即可)
vim /opt/testhaha.py
进程代码如下:
#!/usr/bin/env python
import time
def main():
while True:
print 'test!!'
time.sleep(2)
if __name__ == '__main__':
main()
【使用Supervisor保护进程不死不灭】启动这个进程:
python /opt/testhaha.py
在刚刚第一个终端里使用下面命令即可看到此进程的运行状态:
ps -ef |grep testhaha
编写被守护的进程配置文件
下面我们开始编写监控此进程的配置文件,在
/etc/supervisor.d/
目录下新建testhaha.ini
监控文件的文件名最好与被监控的进程名一致,但是监控文件后缀名为
.ini
。vim /etc/supervisor.d/testhaha.ini
监控文件的配置代码如下:
[program:test]
directory = /opt ;
程序的启动目录
command = python /opt/testhaha.py;
启动命令,这里最好写绝对路径
autostart = true;
在 supervisord 启动的时候也自动启动
startsecs = 5;
启动 5 秒后没有异常退出,就当作已经正常启动了
autorestart = true;
程序异常退出后自动重启
startretries = 3;
启动失败自动重试次数,默认是 3
user = root;
用哪个用户启动
redirect_stderr = true;
把 stderr 重定向到 stdout,默认 false
stdout_logfile_maxbytes = 20MB;
stdout 日志文件大小,默认 50MB
stdout_logfile_backups = 20;
stdout 日志文件备份数
;
stdout 日志文件,需要注意当指定目录不存在时无法正常启动,所以需要手动创建目录(supervisord 会自动创建日志文件)
stdout_logfile = /var/log/supervisor/test_stdout.log
启动supervisord
执行 supervisord 命令,将会启动 supervisord 进程,同时我们在配置文件中设置的进程也会相应启动。
执行启动命令:
supervisord
如果说有警告,不用管它,这是supervisord提醒你正在以root运行它。
如果报错说有其他进程已经占用端口的时候,执行下面命令:
find / -name supervisor.sock
unlink /你系统上显示的路径/supervisor.sock
然后再次执行启动命令。
关于其他报错,文章末尾有问题总结。
使用
ps
命令查看supervisord
是否已启动:ps -ef |grep supervisord | grep -v "grep"
测试监控脚本是否能够复活被监控的进程 切换到另一终端
(Terminal)
,输入:ps -ef |grep testhaha | grep -v "grep"
即可看到该进程的
PID
,并记录下来。此时使用
kill
命令杀死该进程:kill -s 9 28074
其中
-s 9
制定了传递给进程的信号是9,即强制、尽快终止进程。28074
则是上面ps
命令查到的testhaha
的PID
。执行完
kill
命令后,再输入ps
命令查看testhaha
的状态,此时发现,该进程的PID
变了,就是因为被supervisord
重启了。命令详解 初始启动Supervisord,启动、管理配置中设置的进程:
supervisord停止(启动,重启)某一个进程(xxx)/全部:
supervisorctl stop(start, restart) xxx/all只载入最新的配置文件, 并不重启任何进程:
supervisorctl reread载入最新的配置文件,停止原来的所有进程并按新的配置启动管理所有进程:
supervisorctl reload根据最新的配置文件,启动新配置或有改动的进程,配置没有改动的进程不会受影响而重启:
supervisorctl update查看正在守候的进程
supervisorctl启动某个进程(program_name=你被监控程序的配置中[program:xxx]里写的程序名称)
supervisorctl start program_name停止某一进程 (program_name=你被监控程序的配置中[program:xxx]里写的程序名称)
pervisorctl stop program_name重启某一进程 (program_name=你被监控程序的配置中[program:xxx]里写的程序名称)
supervisorctl restart program_name停止全部进程
supervisorctl stop all
注意:显示用stop停止掉的进程,用reload或者update都不会自动重启。
建议 开机自启
Supervisor
以及自我复活将
supervisor
配置成开机启动服务以及定时自检复活
首先先关闭现在正在运行的supervisor
,可以使用kill
命令杀死supervisor
的进程号,步骤不再赘述,文章上半部分有。停止supervisor后,新建一个名为
supervisor.service
的文件vim /lib/systemd/system/supervisor.service
添加以下内容:
[Unit]
Description=supervisor
After=network.target[Service]
Type=forking
ExecStart=/usr/bin/supervisord -c /etc/supervisord.conf
ExecStop=/usr/bin/supervisorctl $OPTIONS shutdown
ExecReload=/usr/bin/supervisorctl $OPTIONS reload
KillMode=process
Restart=always
RestartSec=42s[Install]
WantedBy=multi-user.target
上述文件编写后,执行如下命令即可。
加入开机自启动服务:
systemctl enable supervisor.service
重新载入
systemd
,扫描新的或有变动的单元(必要步骤):systemctl daemon-reload
修改文件权限:
chmod 766 /lib/systemd/system/supervisor.service
然后,启动服务:
systemctl start supervisor.service
可以在查询一下服务状态
systemctl status supervisor.service
把
supervisor
加入systemctl
管理
通过上述过程,实际上supervisor
已经加入了systemctl
管理了,后续起停supervisor
服务都可以通过systemctl
来控制了,systemctl start supervisor.service 启动服务这里注意一下,以后开启
systemctl stop supervisor.service 停止服务
systemctl restart supervisor.service 重新启动服务
systemctl reload supervisor.service 重载配置文件
systemctl status supervisor.service 查看服务状态(显示的类似于操作记录)
supervisor
就可以不用执行supervisord
,如果使用systemctl
启动了supervisor
,再使用supervisor
启动的话会报错。建议统一使用systemctl
进行服务的启停及其他操作。让PIP源使用国内镜像,提升下载速度和安装成功率。
国内源:临时使用:
新版ubuntu要求使用https源,要注意。
清华:https://pypi.tuna.tsinghua.edu.cn/simple
阿里云:http://mirrors.aliyun.com/pypi/simple/
中国科技大学:https://pypi.mirrors.ustc.edu.cn/simple/
华中理工大学:http://pypi.hustunique.com/
山东理工大学:http://pypi.sdutlinux.org/
豆瓣:http://pypi.douban.com/simple/
可以在使用pip的时候加参数
-i https://pypi.tuna.tsinghua.edu.cn/simple例如:
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple pyspider这样就会从清华这边的镜像去安装pyspider库
永久修改,一劳永逸:
Linux
下,修改 ~/.pip/pip.conf
(没有就创建一个文件夹及文件。文件夹要加“.”,表示是隐藏文件夹)内容如下:
[global]
index-url = https://pypi.tuna.tsinghua.edu.cn/simple
[install]
trusted-host=mirrors.aliyun.com
Windows
下,直接在user
目录中创建一个pip
目录,如:C:\Users\xx\pip
,新建文件pip.ini
。内容同上。问题总结 问题一: 针对Ubuntu安装Supervisor报错
网上说:
pip install supervisor
出现问题:
bash:pip:command not found
需要安装:
pip:sudo easy_install pip
出现问题:
sudo: easy_install: command not found
需要执行:
sudo apt-get install python-setuptools
然后就可以:
pip install supervisor
问题二: tmp目录里的文件被系统清空
在
supervisor
默认配置中,其启动的sock
等都会放到tmp
目录,而tmp
目录会自动清理(比如重启主机)导致无法使用supervisorctl
命令;修改
supervisor.conf
文件,修改到/var/run/
及/var/log/
目录,目录随便指定,好记就行。file=/usr/local/supervisor/supervisor.sock
serverurl=unix:///usr/local/supervisor/supervisor.sock
注意:修改supervisor.conf文件后,要执行supervisorctl reload,重新加载配置文件;
问题三:Refused Connection报错
Supervisorctl error: unix:///var/run/supervisord.sock refused connection?
说明需要开启
supervisord
。如果已经修改了
supervisor.conf
,这句就不要执行了,要是执行的话supervisor.conf将被初始化,后果很麻烦。/etc/supervisord.conf
sudo supervisord -c /etc/supervisord.conf
sudo supervisorctl status
问题四:端口被占用报错
Error: Another program is already listening on a port that one of our HTTP servers is configured to use. Shut this program down first before starting
解决方法:
find / -name supervisor.sock
unlink /你系统上显示的路径/supervisor.sock
问题五:没有sock文件报错
unix:///var/run/supervisor.sock no such file
sudo touch /usr/local/supervisor/supervisor.sock
sudo chmod 777 /usr/local/supervisor/supervisor.sock
Restarted supervisord
问题六: Source不认识
关于在command中,执行.sh脚本
请参照此配置文件中command的写法,直接写command=source xxx,会报source不认识:
[program:blog]
command=/bin/bash -c 'source /var/ftp_root/program/blog/startall.sh'
user=root
autostart=true
autorestart=true
redirect_stderr=True
stdout_logfile=/tmp/blog.log
stderr_logfile=/tmp/blog.err
stopasgroup=true
killasgroup=true
问题七:开启web功能无法访问
关闭防火墙 & SELINUX
systemctl stop firewalld.service #停止firewall
systemctl disable firewalld.service #禁止firewall开机启动,重启系统生效
关闭selinux
用 root 用户运行下面的命令
vim /etc/sysconfig/selinux
打开 selinux 文件后,将
SELINUX=enforcing
修改为
SELINUX=disabled
保存后退出。接着再执行如下命令,注意
setenforce
后面有空格:setenforce 0
推荐阅读
- 由浅入深理解AOP
- 【译】20个更有效地使用谷歌搜索的技巧
- mybatisplus如何在xml的连表查询中使用queryWrapper
- MybatisPlus|MybatisPlus LambdaQueryWrapper使用int默认值的坑及解决
- MybatisPlus使用queryWrapper如何实现复杂查询
- iOS中的Block
- Linux下面如何查看tomcat已经使用多少线程
- 使用composer自动加载类文件
- android|android studio中ndk的使用
- 使用协程爬取网页,计算网页数据大小