lyyyuna 的小花园

动静中之动, by

RSS

使用 Supervisor 管理进程
发表于 2017-04

前言

如果需要让某一个进程长期运行,该怎么做?

当终端关闭,终端下所有的进程也会被相应的杀死,即使是被扔到后台执行的 job。然而,要把自己的应用程序专门写成 daemon,会增加开发的负担。这时候,一种万能的、对原应用侵入最小的方法,Supervisor,便走进了我们的视线。

Supervisor 可不光具有后台长期执行程序的功能。先举两个实际的例子。

这些都可以通过 Supervisor,以类似 rc.d 脚本的方式,一劳永逸的解决。

安装

Supervisor 是由 Python 写的,安装十分简单。

pip install supervisor

目前只支持 Python2 (>2.4)。

不过我建议使用包管理器来安装,例如 ubuntu,

apt install supervisor

这样安装完以后会有一个默认的配置文件生成在

/etc/supervisor/supervisord.conf

配置一个后台进程

Supervisor 会按以下顺序搜索配置文件,

配置文件是 Windows 的 INI 格式,我们撇开其他节,直奔主题 [program:x]

假设有一个循环打印 hello 的程序,使用 virtualenv 中的 Python 环境运行,现在需要其在后台常驻运行。

# /root/test/hello.py
import time
while True:
    print 'Hello, world.'
    time.sleep(2)

我们添加一个 [program:x] 小节为

[program:hellotest]
command = /root/test/venv/bin/python -u hello.py
directory = /root/test
user = root
stdout_logfile = /root/test/hello.log
redirect_stderr = true
autostart = false
autorestart = true

注意要添加 -u 启动参数,不然 stdout 上的输出会被一直缓存。首先启动 Supervisor 进程本身,安装的时候其本身已经被添加为 Linux 系统的一个 service

# service supervisor start

然后使用 supervisorctl 工具来启动我们的 hellotest

# supervisorctl start hellotest
hellotest: started

查询 hellotest 的运行状态

# supervisorctl status hellotest
hellotest                        RUNNING   pid 898, uptime 0:02:01

查看 stdout 上的输出

# tailf test/hello.log 
Hello, world.
Hello, world.
Hello, world.
Hello, world.
Hello, world.
Hello, world.
Hello, world.
Hello, world.
Hello, world.
Hello, world.
Hello, world.

如果我们的参数配置错误,还可以查看 Supervisor 自身的 log

/var/log/supervisor/supervisor.log

配置一组后台进程

配置一组后台进程与之类似,首先我们需要多个 [program:x] 小节

[program:hellotest]
command = /root/test/venv/bin/python -u hello.py
directory = /root/test
user = root
stdout_logfile = /root/test/hello.log
redirect_stderr = true
autorestart = true
autostart = false

[program:hellotest2]
command = /root/test/venv/bin/python -u hello2.py
directory = /root/test
user = root
stdout_logfile = /root/test/hello.log
redirect_stderr = true
autorestart = true
autostart = false

[group:hellogroup]
programs = hellotest, hellotest2

启动一组中所有进程时,命令有些不同

supervisorctl start hellogroup:*

一旦一个 program 被加入组中,你就不能再用原先的命令启动

# supervisorctl start hellotest
hellotest: ERROR (no such process)
# supervisorctl start hellogroup:hellotest

验证

我们可以看一下进程的 pid 号来验证我们的 hello 进程确实是 Supervisor 的子进程

# ps -ef | grep 1182
root      1182     1  0 16:07 ?        00:00:00 /usr/bin/python /usr/bin/supervisord -n -c /etc/supervisor/supervisord.conf
root      1226  1182  0 16:12 ?        00:00:00 /root/test/venv/bin/python -u hello2.py
root      1227  1182  0 16:12 ?        00:00:00 /root/test/venv/bin/python -u hello.py

再用 kill 命令验证 Supervisor 具有看门狗功能

# kill -9 1226
# ps -ef | grep 1182
root      1182     1  0 16:07 ?        00:00:00 /usr/bin/python /usr/bin/supervisord -n -c /etc/supervisor/supervisord.conf
root      1227  1182  0 16:12 ?        00:00:00 /root/test/venv/bin/python -u hello.py
root      1255  1182  0 16:18 ?        00:00:00 /root/test/venv/bin/python -u hello2.py

hello2.py 已经是新的 pid 号。