基于Python 的進(jìn)程管理工具supervisor使用指南
Supervisor 是基于 Python 的進(jìn)程管理工具,只能運行在 Unix-Like 的系統(tǒng)上,也就是無法運行在 Windows 上。Supervisor 官方版目前只能運行在 Python 2.4 以上版本,但是還無法運行在 Python 3 上,不過已經(jīng)有一個 Python 3 的移植版 supervisor-py3k。
什么情況下我們需要進(jìn)程管理呢?就是執(zhí)行一些需要以守護(hù)進(jìn)程方式執(zhí)行的程序,比如一個后臺任務(wù),我最常用的是用來啟動和管理基于 Tornado 寫的 Web 程序。
除此之外,Supervisor 還能很友好的管理程序在命令行上輸出的日志,可以將日志重定向到自定義的日志文件中,還能按文件大小對日志進(jìn)行分割。
Supervisor 有兩個主要的組成部分:
- supervisord,運行 Supervisor 時會啟動一個進(jìn)程 supervisord,它負(fù)責(zé)啟動所管理的進(jìn)程,并將所管理的進(jìn)程作為自己的子進(jìn)程來啟動,而且可以在所管理的進(jìn)程出現(xiàn)崩潰時自動重啟。
- supervisorctl,是命令行管理工具,可以用來執(zhí)行 stop、start、restart 等命令,來對這些子進(jìn)程進(jìn)行管理。
安裝
sudo pip install supervisor
創(chuàng)建配置文件
echo_supervisord_conf > /etc/supervisord.conf
如果出現(xiàn)沒有權(quán)限的問題,可以使用這條命令
sudo su - root -c "echo_supervisord_conf > /etc/supervisord.conf"
配置文件說明
想要了解怎么配置需要管理的進(jìn)程,只要打開 supervisord.conf 就可以了,里面有很詳細(xì)的注釋信息。
打開配置文件
vim /etc/supervisord.conf
默認(rèn)的配置文件是下面這樣的,但是這里有個坑需要注意,supervisord.pid 以及 supervisor.sock 是放在 /tmp 目錄下,但是 /tmp 目錄是存放臨時文件,里面的文件是會被 Linux 系統(tǒng)刪除的,一旦這些文件丟失,就無法再通過 supervisorctl 來執(zhí)行 restart 和 stop 命令了,將只會得到 unix:///tmp/supervisor.sock 不存在的錯誤 。
[unix_http_server] ;file=/tmp/supervisor.sock ; (the path to the socket file) ;修改為 /var/run 目錄,避免被系統(tǒng)刪除 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 目錄,避免被系統(tǒng)刪除 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 目錄,避免被系統(tǒng)刪除 pidfile=/var/run/supervisord.pid ; (supervisord pidfile;default supervisord.pid) ... ;設(shè)置啟動supervisord的用戶,一般情況下不要輕易用root用戶來啟動,除非你真的確定要這么做 ;user=chrism ; (default is current user, required if root) ... [supervisorctl] ; 必須和'unix_http_server'里面的設(shè)定匹配 ;serverurl=unix:///tmp/supervisor.sock ; use a unix:// URL for a unix socket ;修改為 /var/run 目錄,避免被系統(tǒng)刪除 serverurl=unix:///var/run/supervisor.sock ; use a unix:// URL for a unix socket ;serverurl=http://127.0.0.1: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 ...
默認(rèn)情況下,進(jìn)程的日志文件達(dá)到50MB時,將進(jìn)行分割,最多保留10個文件,當(dāng)然這些配置也可以對每個進(jìn)程單獨配置。
權(quán)限問題
設(shè)置好配置文件后,應(yīng)先創(chuàng)建上述配置文件中新增的文件夾。如果指定了啟動用戶 user,這里以 oxygen 為例,那么應(yīng)注意相關(guān)文件的權(quán)限問題,包括日志文件,否則會出現(xiàn)沒有權(quán)限的錯誤。例如設(shè)置了啟動用戶 oxygen,然后啟動 supervisord 出現(xiàn)錯誤
Error: Cannot open an HTTP server: socket.error reported errno.EACCES (13)
就是由于上面的配置文件中 /var/run 文件夾,沒有授予啟動 supervisord 的用戶 oxygen 的寫權(quán)限。/var/run 文件夾實際上是鏈接到 /run,因此我們修改 /run 的權(quán)限。
sudo chmod 777 /run
這樣有點簡單粗暴,也可以考慮把上述配置文件中 .sock,.pid 等文件修改到其他文件夾中,并確保有相應(yīng)的權(quán)限即可。一般情況下,我們可以用 root 用戶啟動 supervisord 進(jìn)程,然后在其所管理的進(jìn)程中,再具體指定需要以那個用戶啟動這些進(jìn)程。
使用瀏覽器來管理
supervisor 同時提供了通過瀏覽器來管理進(jìn)程的方法,只需要注釋掉如下幾行就可以了。
;[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://127.0.0.1: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

使用 include
在配置文件的最后,有一個 [include] 的配置項,跟 Nginx 一樣,可以 include 某個文件夾下的所有配置文件,這樣我們就可以為每個進(jìn)程或相關(guān)的幾個進(jìn)程的配置單獨寫成一個文件。
[include] files = /etc/supervisord.d/*.ini
進(jìn)程的配置樣例
一個簡單的例子如下
; 設(shè)置進(jìn)程的名稱,使用 supervisorctl 來管理進(jìn)程時需要使用該進(jìn)程名 [program:your_program_name] command=python server.py --port=9000 ;numprocs=1 ; 默認(rèn)為1 ;process_name=%(program_name)s ; 默認(rèn)為 %(program_name)s,即 [program:x] 中的 x directory=/home/python/tornado_server ; 執(zhí)行 command 之前,先切換到工作目錄 user=oxygen ; 使用 oxygen 用戶來啟動該進(jìn)程 ; 程序崩潰時自動重啟,重啟次數(shù)是有限制的,默認(rèn)為3次 autorestart=true redirect_stderr=true ; 重定向輸出的日志 stdout_logfile = /var/log/supervisord/tornado_server.log loglevel=info
設(shè)置日志級別
loglevel 指定了日志的級別,用 Python 的 print 語句輸出的日志是不會被記錄到日志文件中的,需要搭配 Python 的 logging 模塊來輸出有指定級別的日志。
多個進(jìn)程
按照官方文檔的定義,一個 [program:x] 實際上是表示一組相同特征或同類的進(jìn)程組,也就是說一個 [program:x] 可以啟動多個進(jìn)程。這組進(jìn)程的成員是通過 numprocs 和 process_name 這兩個參數(shù)來確定的,這句話什么意思呢,我們來看這個例子。
; 設(shè)置進(jìn)程的名稱,使用 supervisorctl 來管理進(jìn)程時需要使用該進(jìn)程名 [program:foo] ; 可以在 command 這里用 python 表達(dá)式傳遞不同的參數(shù)給每個進(jìn)程 command=python server.py --port=90%(process_num)02d directory=/home/python/tornado_server ; 執(zhí)行 command 之前,先切換到工作目錄 ; 若 numprocs 不為1,process_name 的表達(dá)式中一定要包含 process_num 來區(qū)分不同的進(jìn)程 numprocs=2 process_name=%(program_name)s_%(process_num)02d; user=oxygen ; 使用 oxygen 用戶來啟動該進(jìn)程 autorestart=true ; 程序崩潰時自動重啟 redirect_stderr=true ; 重定向輸出的日志 stdout_logfile = /var/log/supervisord/tornado_server.log loglevel=info
上面這個例子會啟動兩個進(jìn)程,process_name 分別為 foo:foo_01 和 foo:foo_02。通過這樣一種方式,就可以用一個 [program:x] 配置項,來啟動一組非常類似的進(jìn)程。
再介紹兩個配置項 stopasgroup 和 killasgroup
; 默認(rèn)為 false,如果設(shè)置為 true,當(dāng)進(jìn)程收到 stop 信號時,會自動將該信號發(fā)給該進(jìn)程的子進(jìn)程。如果這個配置項為 true,那么也隱含 killasgroup 為 true。例如在 Debug 模式使用 Flask 時,F(xiàn)lask 不會將接收到的 stop 信號也傳遞給它的子進(jìn)程,因此就需要設(shè)置這個配置項。
stopasgroup=false ; send stop signal to the UNIX process ; 默認(rèn)為 false,如果設(shè)置為 true,當(dāng)進(jìn)程收到 kill 信號時,會自動將該信號發(fā)給該進(jìn)程的子進(jìn)程。如果這個程序使用了 python 的 multiprocessing 時,就能自動停止它的子線程。 killasgroup=false ; SIGKILL the UNIX process group (def false)
更詳細(xì)的配置例子,可以參考如下,官方文檔在這里
;[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)
將多個進(jìn)程按組管理
Supervisor 同時還提供了另外一種進(jìn)程組的管理方式,通過這種方式,可以使用 supervisorctl 命令來管理一組進(jìn)程。跟 [program:x] 的進(jìn)程組不同的是,這里的進(jìn)程是一個個的 [program:x] 。
[group:thegroupname] programs=progname1,progname2 ; each refers to 'x' in [program:x] definitions priority=999 ; the relative start priority (default 999)
當(dāng)添加了上述配置后,progname1 和 progname2 的進(jìn)程名就會變成 thegroupname:progname1 和 thegroupname:progname2 以后就要用這個名字來管理進(jìn)程了,而不是之前的 progname1。
以后執(zhí)行 supervisorctl stop thegroupname: 就能同時結(jié)束 progname1 和 progname2,執(zhí)行 supervisorctl stop thegroupname:progname1 就能結(jié)束 progname1。supervisorctl 的命令我們稍后介紹。
啟動 supervisord
執(zhí)行 supervisord 命令,將會啟動 supervisord 進(jìn)程,同時我們在配置文件中設(shè)置的進(jìn)程也會相應(yīng)啟動。
# 使用默認(rèn)的配置文件 /etc/supervisord.conf supervisord # 明確指定配置文件 supervisord -c /etc/supervisord.conf # 使用 user 用戶啟動 supervisord supervisord -u user
更多參數(shù)請參考文檔
supervisorctl 命令介紹
# 停止某一個進(jìn)程,program_name 為 [program:x] 里的 x supervisorctl stop program_name # 啟動某個進(jìn)程 supervisorctl start program_name # 重啟某個進(jìn)程 supervisorctl restart program_name # 結(jié)束所有屬于名為 groupworker 這個分組的進(jìn)程 (start,restart 同理) supervisorctl stop groupworker: # 結(jié)束 groupworker:name1 這個進(jìn)程 (start,restart 同理) supervisorctl stop groupworker:name1 # 停止全部進(jìn)程,注:start、restart、stop 都不會載入最新的配置文件 supervisorctl stop all # 載入最新的配置文件,停止原有進(jìn)程并按新的配置啟動、管理所有進(jìn)程 supervisorctl reload # 根據(jù)最新的配置文件,啟動新配置或有改動的進(jìn)程,配置沒有改動的進(jìn)程不會受影響而重啟 supervisorctl update
注意:顯示用 stop 停止掉的進(jìn)程,用 reload 或者 update 都不會自動重啟。也可以參考這里
開機自動啟動 Supervisord
Supervisord 默認(rèn)情況下并沒有被安裝成服務(wù),它本身也是一個進(jìn)程。官方已經(jīng)給出了腳本可以將 Supervisord 安裝成服務(wù),可以參考這里查看各種操作系統(tǒng)的安裝腳本,但是我用官方這里給的 Ubuntu 腳本卻無法運行。
安裝方法可以參考 serverfault 上的回答。
比如我是 Ubuntu 系統(tǒng),可以這么安裝,這里選擇了另外一個腳本
# 下載腳本 sudo su - root -c "sudo curl https://gist.githubusercontent.com/howthebodyworks/176149/raw/d60b505a585dda836fadecca8f6b03884153196b/supervisord.sh > /etc/init.d/supervisord" # 設(shè)置該腳本為可以執(zhí)行 sudo chmod +x /etc/init.d/supervisord # 設(shè)置為開機自動運行 sudo update-rc.d supervisord defaults # 試一下,是否工作正常 service supervisord stop service supervisord start
注意:這個腳本下載下來后,還需檢查一下與我們的配置是否相符合,比如默認(rèn)的配置文件路徑,pid 文件路徑等,如果存在不同則需要進(jìn)行一些修改。
其實還有一個簡單的方法,因為 Linux 在啟動的時候會執(zhí)行 /etc/rc.local 里面的腳本,所以只要在這里添加執(zhí)行命令就可以
# 如果是 Ubuntu 添加以下內(nèi)容 /usr/local/bin/supervisord -c /etc/supervisord.conf # 如果是 Centos 添加以下內(nèi)容 /usr/bin/supervisord -c /etc/supervisord.conf
以上內(nèi)容需要添加在 exit 命令前,而且由于在執(zhí)行 rc.local 腳本時,PATH 環(huán)境變量未全部初始化,因此命令需要使用絕對路徑。
在添加前,先在終端測試一下命令是否能正常執(zhí)行,如果找不到 supervisord,可以用如下命令找到
sudo find / -name supervisord
- python測試開發(fā)django之使用supervisord?后臺啟動celery?服務(wù)(worker/beat)
- 在python3中使用Supervisor的詳細(xì)教程
- 使用 Supervisor 監(jiān)控 Python3 進(jìn)程方式
- Python supervisor強大的進(jìn)程管理工具的使用
- python進(jìn)程管理工具supervisor的安裝與使用教程
- Python使用Supervisor來管理進(jìn)程的方法
- python進(jìn)程管理工具supervisor使用實例
- 使用Python的Supervisor進(jìn)行進(jìn)程監(jiān)控以及自動啟動
- python進(jìn)程管理工具supervisor安裝使用
相關(guān)文章
使用Windows批處理和WMI設(shè)置Python的環(huán)境變量方法
今天小編就為大家分享一篇使用Windows批處理和WMI設(shè)置Python的環(huán)境變量方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2019-08-08
Python教程pandas數(shù)據(jù)分析去重復(fù)值
Pandas指定行進(jìn)行去重更新值,加載數(shù)據(jù)sample抽樣函數(shù),指定需要更新的值append直接添加append函數(shù)用法,根據(jù)某一列key值進(jìn)行去重key唯一2021-09-09
Python利用PyExecJS庫執(zhí)行JS函數(shù)的案例分析
這篇文章主要介紹了Python利用PyExecJS庫執(zhí)行JS函數(shù),本文通過案例分析給大家介紹的非常詳細(xì),具有一定的參考借鑒價值,需要的朋友可以參考下2019-12-12

