背景
最近在搭建混沌工程所需要的专项测试环境,原来一般都是直接通过 nohup + &
的方式,但该方式存在一个问题,如果由于服务器重启或者进程被kill掉了,那这个时候就需要再手动的去启动相应的进程。 这样对于只有一两个进程来说还好,但对于需要维护很多台虚拟机或者很多进程的时候则会比较繁琐。所以便牵扯到守护进程一一Supervisor
。
什么是守护进程
在linux或者unix操作系统中,守护进程(Daemon)是一种运行在后台的特殊进程,它独立于控制终端并且周期性的执行某种任务或等待处理某些发生的事件。由于在linux中,每个系统与用户进行交流的界面称为终端,每一个从此终端开始运行的进程都会依附于这个终端,这个终端被称为这些进程的控制终端,当控制终端被关闭的时候,相应的进程都会自动关闭。但是守护进程却能突破这种限制,它脱离于终端并且在后台运行,并且它脱离终端的目的是为了避免进程在运行的过程中的信息在任何终端中显示并且进程也不会被任何终端所产生的终端信息所打断。它从被执行的时候开始运转,直到整个系统关闭才退出。
Supervisor
比较容易弄混淆的几个名词:
- supervisor:要安装的软件的名称;
- supervisord:装好
supervisor
软件后,supervisord
用于启动supervisor
服务; - supervisorctl:用于管理
supervisor
配置文件中program
和supervisor
服务本身。
在 Linux 上有很多可以管理进程的工具,使用 Supervisor 来做这个事情。原因有两点:
- 它是微软官方文档推荐的,降低学习成本。
- 它并不一定是最好的,但一定是文档最全的。
Docker上安装 supervisor
下面主要介绍下在新的Docker环境上安装supervisor的过程中可能遇到的问题。(也可参考supervisor官网的安装方式)
问题一:新启动的Docker,通过yum安装 supervisor 失败。
1 | [root@fafebfab0828 /]# yum install -y supervisor |
即使通过修改了yum源的配置,仍然存在这个问题。
根本原因:新启动的Docker中,不存在 EPEL(Extra Packages for Enterprise Linux)企业版Linux额外包,PHEL分布非标准包的社区类库。
解决方案:
安装EPEL包(推荐)
1
2yum -y install epel-release
yum install -y supervisor通过 Centos pkg 官网 (链接为Centos7,如是其他系统需找到对应链接)找到对应的
supervisor
安装包。⚠️ PS: 其缺点是该安装包如果还依赖其他的包就会挺麻烦,可能还需要按照该方式下载其他的依赖包。
1
2
3
4
5
6# 此时安装 supervisor 还是依赖 python-meld3 和 python-setuptools
[root@28c67f46fd89 home]# rpm -ivh supervisor-3.4.0-1.el7.noarch.rpm
warning: supervisor-3.4.0-1.el7.noarch.rpm: Header V3 RSA/SHA256 Signature, key ID 352c64e5: NOKEY
error: Failed dependencies:
python-meld3 >= 0.6.5 is needed by supervisor-3.4.0-1.el7.noarch
python-setuptools is needed by supervisor-3.4.0-1.el7.noarch
问题二:开机自启动 supervisor 失败
1 | # 开机自启动 |
原因:Docker运行一个容器起来的时候,只是为你提供特定的文件系统层和进程隔离,它给你一个VM的感觉却并不是VM,所以你可能偶尔会想要像在物理机那样使用systemctl start|status|stop来管理服务进程,就会出现上述错误。
需要启动systemd进程, 所以需要特权。解决办法:
1 | # 创建容器 |
使用 supervisor 启动其他进程
下面通过python写了一个简单的demo,通过supervisor来进行自启动以及守护。
编写需要守护的Demo脚本:test.py,对应的目录为:
home/demo/test.py
,具体内容如下:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17import time
import logging
def print_demo():
count = 0
LOG_FORMAT = "%(asctime)s - %(levelname)s - %(message)s"
logging.basicConfig(filename='/home/demo/my.log', level=logging.DEBUG, format=LOG_FORMAT)
while True:
time.sleep(1)
logging.info("=================start print num: [%s]" % count)
count += 1
logging.debug("This is a debug log.")
logging.critical("This is a critical log.")
if __name__ == "__main__":
print_demo()配置
supervisord.d
下的启动脚本。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16[root@28c67f46fd89 demo]# cat /etc/supervisord.d/demo-python.ini
[program:demo_python]
command=python /home/demo/test.py
autorestart=true
user=root
# 该文件更多的配置信息如下:
[program:x]:配置文件必须包括至少一个program,x是program名称,必须写上,不能为空
command:包含一个命令,当这个program启动时执行
directory:执行子进程时supervisord暂时切换到该目录
user:账户名
startsecs:进程从STARING状态转换到RUNNING状态program所需要保持运行的时间(单位:秒)
redirect_stderr:如果是true,则进程的stderr输出被发送回其stdout文件描述符上的supervisord
stdout_logfile:将进程stdout输出到指定文件
stdout_logfile_maxbytes:stdout_logfile指定日志文件最大字节数,默认为50MB,可以加KB、MB或GB等单位
stdout_logfile_backups:要保存的stdout_logfile备份的数量校验是否启动成功。
1
2
3
4
5
6
7
8
9
10
11
12
13[root@28c67f46fd89 ~]# supervisorctl status
demo_python RUNNING pid 12318, uptime 1 day, 22:49:35
# 或者通过ps和查看日志的内容的办法确认是否正常
[root@28c67f46fd89 ~]# ps aux|grep test
hly 552 0.0 0.3 38460 7028 ? S 10:21 0:00 python /home/demo/test.py
root 570 0.0 0.0 9104 828 pts/3 S+ 10:28 0:00 grep --color=auto test
# 对应日志内容:
[root@28c67f46fd89 ~]# cat /home/demo/my.log
2021-11-22 10:23:20,724 - INFO - =================start print num: [22]
2021-11-22 10:23:20,724 - DEBUG - This is a debug log.
2021-11-22 10:23:20,724 - CRITICAL - This is a critical log.
supervisorctl 常用操作
1 | systemctl enable supervisor # 开机自启动 |
2021/12/1分割线
最近又遇到一个新的问题:部分Python服务需要进行虚拟环境的加载,但启动脚本中又不能直接使用source命令。具体的解决方案如下:
1 | # 解决办法 |