Maison > Article > développement back-end > Guide d'utilisation du superviseur de l'outil de gestion de processus basé sur Python
Supervisor est un outil de gestion de processus basé sur Python. Il peut facilement gérer certains programmes qui doivent être exécutés en tant que processus démons, c'est-à-dire des tâches en arrière-plan. Par exemple, il est utilisé pour démarrer et gérer des programmes Web écrits sur la base de Tornado. .
Supervisor est un outil de gestion de processus basé sur Python qui ne peut s'exécuter que sur des systèmes de type Unix, c'est-à-dire qu'il ne peut pas s'exécuter sous Windows. La version officielle de Supervisor ne peut actuellement fonctionner que sur Python 2.4 ou supérieur, mais ne peut pas encore fonctionner sur Python 3. Cependant, il existe déjà une version portée Python 3 Supervisor-py3k.
Dans quelles circonstances avons-nous besoin d'une gestion des processus ? Il s'agit d'exécuter certains programmes qui doivent être exécutés en tant que processus démon, comme une tâche en arrière-plan. Je suis le plus souvent utilisé pour démarrer et gérer des programmes Web écrits sur Tornado.
De plus, Supervisor peut également gérer de manière très conviviale les journaux générés par le programme sur la ligne de commande, rediriger les journaux vers des fichiers journaux personnalisés et diviser les journaux en fonction de la taille du fichier.
Supervisor a deux composants principaux :
supervisord Lors de l'exécution de Supervisor, un processus superviseur sera démarré, qui est responsable du démarrage du processus géré et de la gestion du processus. Le processus est démarré en tant que son propre processus enfant et peut être automatiquement redémarré lorsque le processus géré tombe en panne.
supervisorctl est un outil de gestion de ligne de commande qui peut être utilisé pour exécuter des commandes telles que stop, start et restart pour gérer ces processus enfants.
Installer
sudo pip install supervisor
Créer un fichier de configuration
echo_supervisord_conf > /etc/supervisord.conf
S'il y a un problème sans autorisation, vous pouvez utiliser cette commande
sudo su - root -c "echo_supervisord_conf > /etc/supervisord . conf"
Description du fichier de configuration
Si vous voulez savoir comment configurer les processus qui doivent être gérés, ouvrez simplement superviserd.conf, qui contient des informations très détaillées.
Ouvrez le fichier de configuration
vim /etc/supervisord.conf
Le fichier de configuration par défaut est le suivant, mais il y a un piège dont vous avez besoin auquel il faut prêter attention. superviseur.pid et superviseur.sock sont placés dans le répertoire /tmp, mais le répertoire /tmp stocke les fichiers temporaires, et les fichiers qu'il contient seront supprimés par le système Linux. Une fois ces fichiers perdus, redémarrez et arrêtez. ne peut pas être exécuté via la commande superviseurctl., vous obtiendrez uniquement l'erreur indiquant que unix:///tmp/supervisor.sock n'existe pas.
[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 ...
Par défaut, lorsque le fichier journal d'un processus atteint 50 Mo, il sera divisé et un maximum de 10 fichiers seront conservés. , ces configurations peuvent également être configurées pour chaque processus. Chaque processus est configuré individuellement.
Problèmes d'autorisation
Après avoir configuré le fichier de configuration, vous devez d'abord créer le nouveau dossier dans le fichier de configuration ci-dessus. Si l'utilisateur de démarrage est spécifié, nous prenons ici l'oxygène comme exemple, alors vous devez faire attention aux autorisations des fichiers associés, y compris les fichiers journaux, sinon une erreur sans autorisations se produira. Par exemple, après avoir défini l'utilisateur de démarrage Oxygen, puis démarré Supervisord, une erreur se produit
Erreur : Impossible d'ouvrir un serveur HTTP : socket.error a signalé errno.EACCES (13)
C'est parce que le dossier /var/run dans le fichier de configuration ci-dessus n'accorde pas l'autorisation d'écriture à l'utilisateur Oxygen qui démarre Supervisord. Le dossier /var/run est en fait lié à /run, nous modifions donc les autorisations de /run.
sudo chmod 777 /run
C'est un peu simple et grossier. Vous pouvez également envisager de modifier les fichiers .sock, .pid et autres dans le fichier de configuration ci-dessus vers d'autres dossiers, et assurez-vous que les autorisations correspondantes sont suffisantes. Dans des circonstances normales, nous pouvons utiliser l'utilisateur root pour démarrer le processus superviseur, puis spécifier quel utilisateur doit démarrer ces processus dans les processus qu'il gère.
Utiliser le navigateur pour gérer
le superviseur fournit également une méthode pour gérer le processus via le navigateur, il suffit de commenter les lignes suivantes.
;[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
Utiliser include
à la fin de la configuration fichier, Il existe un élément de configuration [include] Comme Nginx, vous pouvez inclure tous les fichiers de configuration dans un certain dossier, afin que nous puissions écrire un fichier séparé pour la configuration de chaque processus ou de plusieurs processus associés.
[include] files = /etc/supervisord.d/*.ini
Exemple de configuration de processus
Un exemple simple est le suivant
; 设置进程的名称,使用 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
Définir le niveau de journalisation
loglevel spécifie le niveau de journalisation que la sortie des journaux à l'aide de l'instruction d'impression de Python ne sera pas enregistrée dans le fichier journal. vous devez utiliser le module de journalisation de Python pour générer des journaux avec des niveaux spécifiés.
Processus multiples
按照官方文档的定义,一个 [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中文网!