Home  >  Article  >  Backend Development  >  Python-based process management tool supervisor usage guide

Python-based process management tool supervisor usage guide

高洛峰
高洛峰Original
2017-02-22 17:00:331328browse

Supervisor is a Python-based process management tool that can easily manage some programs that need to be executed as daemons, that is, background tasks. For example, it is used to start and manage web programs written based on Tornado.

Supervisor is a Python-based process management tool that can only run on Unix-Like systems, that is, it cannot run on Windows. The official version of Supervisor can currently only run on Python 2.4 or above, but cannot yet run on Python 3. However, there is already a Python 3 ported version supervisor-py3k.

Under what circumstances do we need process management? It is to execute some programs that need to be executed as a daemon process, such as a background task. I am most commonly used to start and manage web programs written based on Tornado.

In addition, Supervisor can also very friendly manage the logs output by the program on the command line, redirect the logs to custom log files, and split the logs according to file size.

Supervisor has two main components:

  1. supervisord. When running Supervisor, a process supervisord will be started. It is responsible for starting the managed process and The process is started as its own child process and can be automatically restarted when the managed process crashes.

  2. supervisorctl is a command line management tool that can be used to execute commands such as stop, start, and restart to manage these child processes.

Install

sudo pip install supervisor

Create a configuration file

##echo_supervisord_conf > /etc/supervisord.conf

If there is a problem without permissions, you can use this command

sudo su - root -c "echo_supervisord_conf > /etc/supervisord.conf"


Configuration file description

Want to know how to configure For processes that need to be managed, just open supervisord.conf, which contains very detailed annotation information.

Open the configuration file

vim /etc/supervisord.conf

The default configuration file is as follows Yes, but there is a pitfall that you need to pay attention to. supervisord.pid and supervisor.sock are placed in the /tmp directory, but the /tmp directory stores temporary files. The files inside will be deleted by the Linux system. Once these files are lost, It is no longer possible to execute the restart and stop commands through supervisorctl, and you will only get the error that unix:///tmp/supervisor.sock does not exist.

[unix_http_server]
;file=/tmp/supervisor.sock  ; (the path to the socket file)
;修改为 /var/run 目录,避免被系统删除
file=/var/run/supervisor.sock  ; (the path to the socket file)
;chmod=0700         ; socket file mode (default 0700)
;chown=nobody:nogroup    ; socket file uid:gid owner
;username=user       ; (default is no username (open server))
;password=123        ; (default is no password (open server))

;[inet_http_server]     ; inet (TCP) server disabled by default
;port=127.0.0.1:9001    ; (ip_address:port specifier, *:port for ;all iface)
;username=user       ; (default is no username (open server))
;password=123        ; (default is no password (open server))
...

[supervisord]
;logfile=/tmp/supervisord.log ; (main log file;default $CWD/supervisord.log)
;修改为 /var/log 目录,避免被系统删除
logfile=/var/log/supervisor/supervisord.log ; (main log file;default $CWD/supervisord.log)
logfile_maxbytes=50MB    ; (max main logfile bytes b4 rotation;default 50MB)
logfile_backups=10      ; (num of main logfile rotation backups;default 10)
loglevel=info        ; (log level;default info; others: debug,warn,trace)
;pidfile=/tmp/supervisord.pid ; (supervisord pidfile;default supervisord.pid)
;修改为 /var/run 目录,避免被系统删除
pidfile=/var/run/supervisord.pid ; (supervisord pidfile;default supervisord.pid)
...
;设置启动supervisord的用户,一般情况下不要轻易用root用户来启动,除非你真的确定要这么做
;user=chrism         ; (default is current user, required if root)
...

[supervisorctl]
; 必须和'unix_http_server'里面的设定匹配
;serverurl=unix:///tmp/supervisor.sock ; use a unix:// URL for a unix socket
;修改为 /var/run 目录,避免被系统删除
serverurl=unix:///var/run/supervisor.sock ; use a unix:// URL for a unix socket
;serverurl=http://www.php.cn/: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
...

By default, when the log file of a process reaches 50MB, it will be split and a maximum of 10 files will be retained. Of course, these configurations can also be configured for each process. Configure individually.

Permission issues

After setting up the configuration file, you should first create the new folder in the above configuration file. If the startup user user is specified, here we take oxygen as an example, then you should pay attention to the permissions of related files, including log files, otherwise an error without permissions will occur. For example, after setting the startup user oxygen, and then starting supervisord, an error occurs

Error: Cannot open an HTTP server: socket.error reported errno.EACCES (13)

It is because the /var/run folder in the above configuration file does not grant write permission to the user oxygen who starts supervisord. The /var/run folder is actually linked to /run, so we modify the permissions of /run.

sudo chmod 777 /run

This is a bit simple and crude. You can also consider modifying the .sock, .pid and other files in the above configuration file to other files. folder and make sure you have the appropriate permissions. Under normal circumstances, we can use the root user to start the supervisord process, and then specify which user needs to start these processes in the processes it manages.

Use the browser to manage

supervisor also provides a method to manage the process through the browser, just comment out the following lines.

;[inet_http_server]     ; inet (TCP) server disabled by default
;port=127.0.0.1:9001    ; (ip_address:port specifier, *:port for ;all iface)
;username=user       ; (default is no username (open server))
;password=123        ; (default is no password (open server))

[supervisorctl]
...
;serverurl=http://www.php.cn/: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

基于Python 的进程管理工具supervisor使用指南

Use include

At the end of the configuration file, there is The [include] configuration item, like Nginx, can include all configuration files in a certain folder, so that we can write a separate file for the configuration of each process or several related processes.

[include]
files = /etc/supervisord.d/*.ini

Process configuration example

A simple example is as follows

; 设置进程的名称,使用 supervisorctl 来管理进程时需要使用该进程名
[program:your_program_name] 
command=python server.py --port=9000
;numprocs=1         ; 默认为1
;process_name=%(program_name)s  ; 默认为 %(program_name)s,即 [program:x] 中的 x
directory=/home/python/tornado_server ; 执行 command 之前,先切换到工作目录
user=oxygen         ; 使用 oxygen 用户来启动该进程
; 程序崩溃时自动重启,重启次数是有限制的,默认为3次
autorestart=true      
redirect_stderr=true    ; 重定向输出的日志
stdout_logfile = /var/log/supervisord/tornado_server.log
loglevel=info

Set the log level

loglevel specifies the log level. Logs output using Python’s print statement will not be recorded in the log file. , it needs to be paired with Python's logging module to output logs with specified levels.

Multiple processes

按照官方文档的定义,一个 [program:x] 实际上是表示一组相同特征或同类的进程组,也就是说一个 [program:x] 可以启动多个进程。这组进程的成员是通过 numprocs 和 process_name 这两个参数来确定的,这句话什么意思呢,我们来看这个例子。

; 设置进程的名称,使用 supervisorctl 来管理进程时需要使用该进程名
[program:foo] 
; 可以在 command 这里用 python 表达式传递不同的参数给每个进程
command=python server.py --port=90%(process_num)02d
directory=/home/python/tornado_server ; 执行 command 之前,先切换到工作目录
; 若 numprocs 不为1,process_name 的表达式中一定要包含 process_num 来区分不同的进程
numprocs=2          
process_name=%(program_name)s_%(process_num)02d; 
user=oxygen         ; 使用 oxygen 用户来启动该进程
autorestart=true      ; 程序崩溃时自动重启
redirect_stderr=true    ; 重定向输出的日志
stdout_logfile = /var/log/supervisord/tornado_server.log
loglevel=info

上面这个例子会启动两个进程,process_name 分别为 foo:foo_01 和 foo:foo_02。通过这样一种方式,就可以用一个 [program:x] 配置项,来启动一组非常类似的进程。

再介绍两个配置项 stopasgroup 和 killasgroup

; 默认为 false,如果设置为 true,当进程收到 stop 信号时,会自动将该信号发给该进程的子进程。如果这个配置项为 true,那么也隐含 killasgroup 为 true。例如在 Debug 模式使用 Flask 时,Flask 不会将接收到的 stop 信号也传递给它的子进程,因此就需要设置这个配置项。

stopasgroup=false       ; send stop signal to the UNIX process 

; 默认为 false,如果设置为 true,当进程收到 kill 信号时,会自动将该信号发给该进程的子进程。如果这个程序使用了 python 的 multiprocessing 时,就能自动停止它的子线程。
killasgroup=false       ; SIGKILL the UNIX process group (def false)

更详细的配置例子,可以参考如下,官方文档在这里

;[program:theprogramname]
;command=/bin/cat       ; the program (relative uses PATH, can take args)
;process_name=%(program_name)s ; process_name expr (default %(program_name)s)
;numprocs=1          ; number of processes copies to start (def 1)
;directory=/tmp        ; directory to cwd to before exec (def no cwd)
;umask=022           ; umask for process (default None)
;priority=999         ; the relative start priority (default 999)
;autostart=true        ; start at supervisord start (default: true)
;autorestart=unexpected    ; whether/when to restart (default: unexpected)
;startsecs=1          ; number of secs prog must stay running (def. 1)
;startretries=3        ; max # of serial start failures (default 3)
;exitcodes=0,2         ; 'expected' exit codes for process (default 0,2)
;stopsignal=QUIT        ; signal used to kill process (default TERM)
;stopwaitsecs=10        ; max num secs to wait b4 SIGKILL (default 10)
;stopasgroup=false       ; send stop signal to the UNIX process group (default false)
;killasgroup=false       ; SIGKILL the UNIX process group (def false)
;user=chrism          ; setuid to this UNIX account to run the program
;redirect_stderr=true     ; redirect proc stderr to stdout (default false)
;stdout_logfile=/a/path    ; stdout log path, NONE for none; default AUTO
;stdout_logfile_maxbytes=1MB  ; max # logfile bytes b4 rotation (default 50MB)
;stdout_logfile_backups=10   ; # of stdout logfile backups (default 10)
;stdout_capture_maxbytes=1MB  ; number of bytes in 'capturemode' (default 0)
;stdout_events_enabled=false  ; emit events on stdout writes (default false)
;stderr_logfile=/a/path    ; stderr log path, NONE for none; default AUTO
;stderr_logfile_maxbytes=1MB  ; max # logfile bytes b4 rotation (default 50MB)
;stderr_logfile_backups=10   ; # of stderr logfile backups (default 10)
;stderr_capture_maxbytes=1MB  ; number of bytes in 'capturemode' (default 0)
;stderr_events_enabled=false  ; emit events on stderr writes (default false)
;environment=A="1",B="2"    ; process environment additions (def no adds)
;serverurl=AUTO        ; override serverurl computation (childutils)

将多个进程按组管理

Supervisor 同时还提供了另外一种进程组的管理方式,通过这种方式,可以使用 supervisorctl 命令来管理一组进程。跟 [program:x] 的进程组不同的是,这里的进程是一个个的 [program:x] 。

[group:thegroupname]
programs=progname1,progname2 ; each refers to 'x' in [program:x] definitions
priority=999         ; the relative start priority (default 999)

当添加了上述配置后,progname1 和 progname2 的进程名就会变成 thegroupname:progname1 和 thegroupname:progname2 以后就要用这个名字来管理进程了,而不是之前的 progname1。

以后执行 supervisorctl stop thegroupname: 就能同时结束 progname1 和 progname2,执行 supervisorctl stop thegroupname:progname1 就能结束 progname1。supervisorctl 的命令我们稍后介绍。

启动 supervisord

执行 supervisord 命令,将会启动 supervisord 进程,同时我们在配置文件中设置的进程也会相应启动。

# 使用默认的配置文件 /etc/supervisord.conf
supervisord
# 明确指定配置文件
supervisord -c /etc/supervisord.conf
# 使用 user 用户启动 supervisord
supervisord -u user

更多参数请参考文档

supervisorctl 命令介绍

# 停止某一个进程,program_name 为 [program:x] 里的 x
supervisorctl stop program_name
# 启动某个进程
supervisorctl start program_name
# 重启某个进程
supervisorctl restart program_name
# 结束所有属于名为 groupworker 这个分组的进程 (start,restart 同理)
supervisorctl stop groupworker:
# 结束 groupworker:name1 这个进程 (start,restart 同理)
supervisorctl stop groupworker:name1
# 停止全部进程,注:start、restart、stop 都不会载入最新的配置文件
supervisorctl stop all
# 载入最新的配置文件,停止原有进程并按新的配置启动、管理所有进程
supervisorctl reload
# 根据最新的配置文件,启动新配置或有改动的进程,配置没有改动的进程不会受影响而重启
supervisorctl update

注意:显示用 stop 停止掉的进程,用 reload 或者 update 都不会自动重启。也可以参考这里

开机自动启动 Supervisord

Supervisord 默认情况下并没有被安装成服务,它本身也是一个进程。官方已经给出了脚本可以将 Supervisord 安装成服务,可以参考这里查看各种操作系统的安装脚本,但是我用官方这里给的 Ubuntu 脚本却无法运行。

安装方法可以参考 serverfault 上的回答。

比如我是 Ubuntu 系统,可以这么安装,这里选择了另外一个脚本

# 下载脚本
sudo su - root -c "sudo curl http://www.php.cn/ > /etc/init.d/supervisord"
# 设置该脚本为可以执行
sudo chmod +x /etc/init.d/supervisord
# 设置为开机自动运行
sudo update-rc.d supervisord defaults
# 试一下,是否工作正常
service supervisord stop
service supervisord start

注意:这个脚本下载下来后,还需检查一下与我们的配置是否相符合,比如默认的配置文件路径,pid 文件路径等,如果存在不同则需要进行一些修改。

其实还有一个简单的方法,因为 Linux 在启动的时候会执行 /etc/rc.local 里面的脚本,所以只要在这里添加执行命令就可以

# 如果是 Ubuntu 添加以下内容
/usr/local/bin/supervisord -c /etc/supervisord.conf

# 如果是 Centos 添加以下内容
/usr/bin/supervisord -c /etc/supervisord.conf

以上内容需要添加在 exit 命令前,而且由于在执行 rc.local 脚本时,PATH 环境变量未全部初始化,因此命令需要使用绝对路径。

在添加前,先在终端测试一下命令是否能正常执行,如果找不到 supervisord,可以用如下命令找到

sudo find / -name supervisord


更多基于Python 的进程管理工具supervisor使用指南相关文章请关注PHP中文网!


Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn