Heim >Backend-Entwicklung >Python-Tutorial >Leitfaden zur Verwendung des Python-basierten Prozessmanagement-Tools für Supervisoren
Supervisor ist ein auf Python basierendes Prozessverwaltungstool, mit dem einige Programme, die als Daemon-Prozesse ausgeführt werden müssen, problemlos verwaltet werden können. Beispielsweise wird es zum Starten und Verwalten von auf Tornado geschriebenen Webprogrammen verwendet .
Supervisor ist ein Python-basiertes Prozessmanagement-Tool, das nur auf Unix-ähnlichen Systemen, also nicht unter Windows, ausgeführt werden kann. Die offizielle Version von Supervisor kann derzeit nur auf Python 2.4 oder höher ausgeführt werden, jedoch noch nicht auf Python 3. Es gibt jedoch bereits eine Python 3-portierte Version supervisor-py3k.
Unter welchen Umständen brauchen wir Prozessmanagement? Es dient dazu, einige Programme auszuführen, die als Daemon-Prozess ausgeführt werden müssen, z. B. eine Hintergrundaufgabe, die ich am häufigsten zum Starten und Verwalten von auf Tornado geschriebenen Webprogrammen verwende.
Darüber hinaus kann Supervisor auch die vom Programm auf der Befehlszeile ausgegebenen Protokolle sehr benutzerfreundlich verwalten, die Protokolle in benutzerdefinierte Protokolldateien umleiten und die Protokolle entsprechend der Dateigröße aufteilen.
Supervisor besteht aus zwei Hauptkomponenten:
supervisord Beim Ausführen von Supervisor wird ein Prozess-Supervisor gestartet, der für den Start des verwalteten Prozesses und die Verwaltung des Prozesses verantwortlich ist. Der Prozess wird als eigener untergeordneter Prozess gestartet und kann automatisch neu gestartet werden, wenn der verwaltete Prozess abstürzt.
supervisorctl ist ein Befehlszeilenverwaltungstool, mit dem Befehle wie Stopp, Start und Neustart ausgeführt werden können, um diese untergeordneten Prozesse zu verwalten.
Installieren
sudo pip install supervisor
Konfigurationsdatei erstellen
echo_supervisord_conf > /etc/supervisord.conf
Wenn es ein Problem ohne Erlaubnis gibt, können Sie diesen Befehl verwenden
sudo su - root -c "echo_supervisord_conf > /etc/supervisord . conf"
Beschreibung der Konfigurationsdatei
Wenn Sie wissen möchten, wie Sie die zu verwaltenden Prozesse konfigurieren, öffnen Sie einfach supervisord.conf verfügt über sehr detaillierte Informationen.
Öffnen Sie die Konfigurationsdatei
vim /etc/supervisord.conf
Die Standardkonfigurationsdatei lautet wie folgt, es gibt jedoch eine Gefahr, die Sie benötigen Beachten Sie, dass supervisord.pid und supervisor.sock im Verzeichnis /tmp abgelegt sind, aber das Verzeichnis /tmp speichert temporäre Dateien und die darin enthaltenen Dateien werden vom Linux-System gelöscht. Starten Sie es neu und stoppen Sie es kann nicht über den Befehl supervisorctl ausgeführt werden, Sie erhalten nur die Fehlermeldung, dass unix:///tmp/supervisor.sock nicht existiert.
[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 ...
Wenn die Protokolldatei eines Prozesses 50 MB erreicht, wird sie standardmäßig aufgeteilt und maximal 10 Dateien bleiben erhalten , diese Konfigurationen können auch für jeden Prozess konfiguriert werden. Jeder Prozess wird individuell konfiguriert.
Berechtigungsprobleme
Nach dem Einrichten der Konfigurationsdatei sollten Sie zunächst den neuen Ordner in der obigen Konfigurationsdatei erstellen. Wenn der Startbenutzerbenutzer angegeben ist (hier nehmen wir Sauerstoff als Beispiel), sollten Sie auf die Berechtigungen der zugehörigen Dateien, einschließlich der Protokolldateien, achten, da sonst ein Fehler ohne Berechtigungen auftritt. Beispielsweise tritt nach dem Festlegen des Startbenutzers Oxygen und dem anschließenden Starten von Supervisord ein Fehler auf
Fehler: HTTP-Server kann nicht geöffnet werden: socket.error gemeldet errno.EACCES (13)
Das liegt daran, dass der Ordner /var/run in der obigen Konfigurationsdatei dem Benutzer Oxygen, der Supervisord startet, keine Schreibberechtigung gewährt. Der Ordner /var/run ist tatsächlich mit /run verknüpft, daher ändern wir die Berechtigungen von /run.
sudo chmod 777 /run
Das ist etwas einfach und grob. Sie können auch erwägen, die .sock-, .pid- und anderen Dateien in der obigen Konfigurationsdatei in andere Ordner zu ändern Stellen Sie sicher, dass die entsprechenden Berechtigungen ausreichend sind. Unter normalen Umständen können wir den Root-Benutzer verwenden, um den Supervisord-Prozess zu starten, und dann angeben, welcher Benutzer diese Prozesse in den von ihm verwalteten Prozessen starten muss.
Verwenden Sie den Browser zum Verwalten
Supervisor bietet auch eine Methode zum Verwalten des Prozesses über den Browser. Kommentieren Sie einfach die folgenden Zeilen aus.
;[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
Verwenden Sie include
am Ende der Konfiguration Datei, Es gibt ein Konfigurationselement [include], mit dem Sie alle Konfigurationsdateien in einen bestimmten Ordner einschließen können, sodass wir für die Konfiguration jedes Prozesses oder mehrerer verwandter Prozesse eine separate Datei schreiben können.
[include] files = /etc/supervisord.d/*.ini
Beispiel für eine Prozesskonfiguration
Ein einfaches Beispiel ist wie folgt
; 设置进程的名称,使用 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
Protokollebene festlegen
Protokolle, die mit der Druckanweisung von Python ausgegeben werden, werden nicht in der Protokolldatei aufgezeichnet. Sie müssen das Protokollierungsmodul von Python verwenden, um Protokolle mit bestimmten Ebenen auszugeben.
Mehrere Prozesse
按照官方文档的定义,一个 [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中文网!