基于Python 的進(jìn)程管理工具supervisor使用指南
Supervisor 是基于 Python 的進(jìn)程管理工具,只能運(yùn)行在 Unix-Like 的系統(tǒng)上,也就是無(wú)法運(yùn)行在 Windows 上。Supervisor 官方版目前只能運(yùn)行在 Python 2.4 以上版本,但是還無(wú)法運(yùn)行在 Python 3 上,不過(guò)已經(jīng)有一個(gè) Python 3 的移植版 supervisor-py3k。
什么情況下我們需要進(jìn)程管理呢?就是執(zhí)行一些需要以守護(hù)進(jìn)程方式執(zhí)行的程序,比如一個(gè)后臺(tái)任務(wù),我最常用的是用來(lái)啟動(dòng)和管理基于 Tornado 寫的 Web 程序。
除此之外,Supervisor 還能很友好的管理程序在命令行上輸出的日志,可以將日志重定向到自定義的日志文件中,還能按文件大小對(duì)日志進(jìn)行分割。
Supervisor 有兩個(gè)主要的組成部分:
- supervisord,運(yùn)行 Supervisor 時(shí)會(huì)啟動(dòng)一個(gè)進(jìn)程 supervisord,它負(fù)責(zé)啟動(dòng)所管理的進(jìn)程,并將所管理的進(jìn)程作為自己的子進(jìn)程來(lái)啟動(dòng),而且可以在所管理的進(jìn)程出現(xiàn)崩潰時(shí)自動(dòng)重啟。
- supervisorctl,是命令行管理工具,可以用來(lái)執(zhí)行 stop、start、restart 等命令,來(lái)對(duì)這些子進(jìn)程進(jìn)行管理。
安裝
sudo pip install supervisor
創(chuàng)建配置文件
echo_supervisord_conf > /etc/supervisord.conf
如果出現(xiàn)沒有權(quán)限的問(wèn)題,可以使用這條命令
sudo su - root -c "echo_supervisord_conf > /etc/supervisord.conf"
配置文件說(shuō)明
想要了解怎么配置需要管理的進(jìn)程,只要打開 supervisord.conf 就可以了,里面有很詳細(xì)的注釋信息。
打開配置文件
vim /etc/supervisord.conf
默認(rèn)的配置文件是下面這樣的,但是這里有個(gè)坑需要注意,supervisord.pid 以及 supervisor.sock 是放在 /tmp 目錄下,但是 /tmp 目錄是存放臨時(shí)文件,里面的文件是會(huì)被 Linux 系統(tǒng)刪除的,一旦這些文件丟失,就無(wú)法再通過(guò) supervisorctl 來(lái)執(zhí)行 restart 和 stop 命令了,將只會(huì)得到 unix:///tmp/supervisor.sock 不存在的錯(cuò)誤 。
[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è)置啟動(dòng)supervisord的用戶,一般情況下不要輕易用root用戶來(lái)啟動(dòng),除非你真的確定要這么做 ;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時(shí),將進(jìn)行分割,最多保留10個(gè)文件,當(dāng)然這些配置也可以對(duì)每個(gè)進(jìn)程單獨(dú)配置。
權(quán)限問(wèn)題
設(shè)置好配置文件后,應(yīng)先創(chuàng)建上述配置文件中新增的文件夾。如果指定了啟動(dòng)用戶 user,這里以 oxygen 為例,那么應(yīng)注意相關(guān)文件的權(quán)限問(wèn)題,包括日志文件,否則會(huì)出現(xiàn)沒有權(quán)限的錯(cuò)誤。例如設(shè)置了啟動(dòng)用戶 oxygen,然后啟動(dòng) supervisord 出現(xiàn)錯(cuò)誤
Error: Cannot open an HTTP server: socket.error reported errno.EACCES (13)
就是由于上面的配置文件中 /var/run 文件夾,沒有授予啟動(dòng) supervisord 的用戶 oxygen 的寫權(quán)限。/var/run 文件夾實(shí)際上是鏈接到 /run,因此我們修改 /run 的權(quán)限。
sudo chmod 777 /run
這樣有點(diǎn)簡(jiǎn)單粗暴,也可以考慮把上述配置文件中 .sock,.pid 等文件修改到其他文件夾中,并確保有相應(yīng)的權(quán)限即可。一般情況下,我們可以用 root 用戶啟動(dòng) supervisord 進(jìn)程,然后在其所管理的進(jìn)程中,再具體指定需要以那個(gè)用戶啟動(dòng)這些進(jìn)程。
使用瀏覽器來(lái)管理
supervisor 同時(shí)提供了通過(guò)瀏覽器來(lái)管理進(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
在配置文件的最后,有一個(gè) [include] 的配置項(xiàng),跟 Nginx 一樣,可以 include 某個(gè)文件夾下的所有配置文件,這樣我們就可以為每個(gè)進(jìn)程或相關(guān)的幾個(gè)進(jìn)程的配置單獨(dú)寫成一個(gè)文件。
[include] files = /etc/supervisord.d/*.ini
進(jìn)程的配置樣例
一個(gè)簡(jiǎn)單的例子如下
; 設(shè)置進(jìn)程的名稱,使用 supervisorctl 來(lái)管理進(jìn)程時(shí)需要使用該進(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 用戶來(lái)啟動(dòng)該進(jìn)程 ; 程序崩潰時(shí)自動(dòng)重啟,重啟次數(shù)是有限制的,默認(rèn)為3次 autorestart=true redirect_stderr=true ; 重定向輸出的日志 stdout_logfile = /var/log/supervisord/tornado_server.log loglevel=info
設(shè)置日志級(jí)別
loglevel 指定了日志的級(jí)別,用 Python 的 print 語(yǔ)句輸出的日志是不會(huì)被記錄到日志文件中的,需要搭配 Python 的 logging 模塊來(lái)輸出有指定級(jí)別的日志。
多個(gè)進(jìn)程
按照官方文檔的定義,一個(gè) [program:x] 實(shí)際上是表示一組相同特征或同類的進(jìn)程組,也就是說(shuō)一個(gè) [program:x] 可以啟動(dòng)多個(gè)進(jìn)程。這組進(jìn)程的成員是通過(guò) numprocs 和 process_name 這兩個(gè)參數(shù)來(lái)確定的,這句話什么意思呢,我們來(lái)看這個(gè)例子。
; 設(shè)置進(jìn)程的名稱,使用 supervisorctl 來(lái)管理進(jìn)程時(shí)需要使用該進(jìn)程名 [program:foo] ; 可以在 command 這里用 python 表達(dá)式傳遞不同的參數(shù)給每個(gè)進(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 來(lái)區(qū)分不同的進(jìn)程 numprocs=2 process_name=%(program_name)s_%(process_num)02d; user=oxygen ; 使用 oxygen 用戶來(lái)啟動(dòng)該進(jìn)程 autorestart=true ; 程序崩潰時(shí)自動(dòng)重啟 redirect_stderr=true ; 重定向輸出的日志 stdout_logfile = /var/log/supervisord/tornado_server.log loglevel=info
上面這個(gè)例子會(huì)啟動(dòng)兩個(gè)進(jìn)程,process_name 分別為 foo:foo_01 和 foo:foo_02。通過(guò)這樣一種方式,就可以用一個(gè) [program:x] 配置項(xiàng),來(lái)啟動(dòng)一組非常類似的進(jìn)程。
再介紹兩個(gè)配置項(xiàng) stopasgroup 和 killasgroup
; 默認(rèn)為 false,如果設(shè)置為 true,當(dāng)進(jìn)程收到 stop 信號(hào)時(shí),會(huì)自動(dòng)將該信號(hào)發(fā)給該進(jìn)程的子進(jìn)程。如果這個(gè)配置項(xiàng)為 true,那么也隱含 killasgroup 為 true。例如在 Debug 模式使用 Flask 時(shí),F(xiàn)lask 不會(huì)將接收到的 stop 信號(hào)也傳遞給它的子進(jìn)程,因此就需要設(shè)置這個(gè)配置項(xiàng)。
stopasgroup=false ; send stop signal to the UNIX process ; 默認(rèn)為 false,如果設(shè)置為 true,當(dāng)進(jìn)程收到 kill 信號(hào)時(shí),會(huì)自動(dòng)將該信號(hào)發(fā)給該進(jìn)程的子進(jìn)程。如果這個(gè)程序使用了 python 的 multiprocessing 時(shí),就能自動(dòng)停止它的子線程。 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)
將多個(gè)進(jìn)程按組管理
Supervisor 同時(shí)還提供了另外一種進(jìn)程組的管理方式,通過(guò)這種方式,可以使用 supervisorctl 命令來(lái)管理一組進(jìn)程。跟 [program:x] 的進(jìn)程組不同的是,這里的進(jìn)程是一個(gè)個(gè)的 [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)程名就會(huì)變成 thegroupname:progname1 和 thegroupname:progname2 以后就要用這個(gè)名字來(lái)管理進(jìn)程了,而不是之前的 progname1。
以后執(zhí)行 supervisorctl stop thegroupname: 就能同時(shí)結(jié)束 progname1 和 progname2,執(zhí)行 supervisorctl stop thegroupname:progname1 就能結(jié)束 progname1。supervisorctl 的命令我們稍后介紹。
啟動(dòng) supervisord
執(zhí)行 supervisord 命令,將會(huì)啟動(dòng) supervisord 進(jìn)程,同時(shí)我們?cè)谂渲梦募性O(shè)置的進(jìn)程也會(huì)相應(yīng)啟動(dòng)。
# 使用默認(rèn)的配置文件 /etc/supervisord.conf supervisord # 明確指定配置文件 supervisord -c /etc/supervisord.conf # 使用 user 用戶啟動(dòng) supervisord supervisord -u user
更多參數(shù)請(qǐng)參考文檔
supervisorctl 命令介紹
# 停止某一個(gè)進(jìn)程,program_name 為 [program:x] 里的 x supervisorctl stop program_name # 啟動(dòng)某個(gè)進(jìn)程 supervisorctl start program_name # 重啟某個(gè)進(jìn)程 supervisorctl restart program_name # 結(jié)束所有屬于名為 groupworker 這個(gè)分組的進(jìn)程 (start,restart 同理) supervisorctl stop groupworker: # 結(jié)束 groupworker:name1 這個(gè)進(jìn)程 (start,restart 同理) supervisorctl stop groupworker:name1 # 停止全部進(jìn)程,注:start、restart、stop 都不會(huì)載入最新的配置文件 supervisorctl stop all # 載入最新的配置文件,停止原有進(jìn)程并按新的配置啟動(dòng)、管理所有進(jìn)程 supervisorctl reload # 根據(jù)最新的配置文件,啟動(dòng)新配置或有改動(dòng)的進(jìn)程,配置沒有改動(dòng)的進(jìn)程不會(huì)受影響而重啟 supervisorctl update
注意:顯示用 stop 停止掉的進(jìn)程,用 reload 或者 update 都不會(huì)自動(dòng)重啟。也可以參考這里
開機(jī)自動(dòng)啟動(dòng) Supervisord
Supervisord 默認(rèn)情況下并沒有被安裝成服務(wù),它本身也是一個(gè)進(jìn)程。官方已經(jīng)給出了腳本可以將 Supervisord 安裝成服務(wù),可以參考這里查看各種操作系統(tǒng)的安裝腳本,但是我用官方這里給的 Ubuntu 腳本卻無(wú)法運(yùn)行。
安裝方法可以參考 serverfault 上的回答。
比如我是 Ubuntu 系統(tǒng),可以這么安裝,這里選擇了另外一個(gè)腳本
# 下載腳本 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è)置為開機(jī)自動(dòng)運(yùn)行 sudo update-rc.d supervisord defaults # 試一下,是否工作正常 service supervisord stop service supervisord start
注意:這個(gè)腳本下載下來(lái)后,還需檢查一下與我們的配置是否相符合,比如默認(rèn)的配置文件路徑,pid 文件路徑等,如果存在不同則需要進(jìn)行一些修改。
其實(shí)還有一個(gè)簡(jiǎn)單的方法,因?yàn)?Linux 在啟動(dòng)的時(shí)候會(huì)執(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 腳本時(shí),PATH 環(huán)境變量未全部初始化,因此命令需要使用絕對(duì)路徑。
在添加前,先在終端測(cè)試一下命令是否能正常執(zhí)行,如果找不到 supervisord,可以用如下命令找到
sudo find / -name supervisord
- python測(cè)試開發(fā)django之使用supervisord?后臺(tái)啟動(dòng)celery?服務(wù)(worker/beat)
- 在python3中使用Supervisor的詳細(xì)教程
- 使用 Supervisor 監(jiān)控 Python3 進(jìn)程方式
- Python supervisor強(qiáng)大的進(jìn)程管理工具的使用
- python進(jìn)程管理工具supervisor的安裝與使用教程
- Python使用Supervisor來(lái)管理進(jìn)程的方法
- python進(jìn)程管理工具supervisor使用實(shí)例
- 使用Python的Supervisor進(jìn)行進(jìn)程監(jiān)控以及自動(dòng)啟動(dòng)
- python進(jìn)程管理工具supervisor安裝使用
相關(guān)文章
Django框架模板語(yǔ)言實(shí)例小結(jié)【變量,標(biāo)簽,過(guò)濾器,繼承,html轉(zhuǎn)義】
這篇文章主要介紹了Django框架模板語(yǔ)言,結(jié)合實(shí)例形式總結(jié)分析了Django框架中變量,標(biāo)簽,過(guò)濾器,繼承,html轉(zhuǎn)義等相關(guān)模板語(yǔ)言操作技巧,需要的朋友可以參考下2019-05-05python如何統(tǒng)計(jì)代碼運(yùn)行的時(shí)長(zhǎng)
這篇文章主要介紹了python如何統(tǒng)計(jì)代碼運(yùn)行的時(shí)長(zhǎng),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-07-07如何使用yolov5輸出檢測(cè)到的目標(biāo)坐標(biāo)信息
YOLOv5是一系列在 COCO 數(shù)據(jù)集上預(yù)訓(xùn)練的對(duì)象檢測(cè)架構(gòu)和模型,下面這篇文章主要給大家介紹了關(guān)于如何使用yolov5輸出檢測(cè)到的目標(biāo)坐標(biāo)信息的相關(guān)資料,需要的朋友可以參考下2022-03-03對(duì)numpy中的transpose和swapaxes函數(shù)詳解
今天小編就為大家分享一篇對(duì)numpy中的transpose和swapaxes函數(shù)詳解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-08-08詳解Python中的偏函數(shù)(Partial Functions)
Python中的偏函數(shù)是來(lái)自函數(shù)式編程的一個(gè)強(qiáng)大工具,它的主要目標(biāo)是減少函數(shù)調(diào)用的復(fù)雜性這個(gè)概念可能起初看起來(lái)有點(diǎn)困難理解,但一旦你明白了它的工作方式,它可能會(huì)成為你的編程工具箱中的重要組成部分,文中有相關(guān)的代碼介紹,需要的朋友可以參考下2023-06-06關(guān)于AnacondaNavigator?Jupyter?Notebook更換Python內(nèi)核的問(wèn)題
因?yàn)樾掳惭b的Anaconda?Navigator默認(rèn)安裝了一個(gè)Python,Jupyter?Notebook默認(rèn)使用的內(nèi)核就是這個(gè)Python,跟我系統(tǒng)安裝好的Python沖突了,下面小編給大家介紹AnacondaNavigator?Jupyter?Notebook更換Python內(nèi)核的問(wèn)題,需要的朋友可以參考下2022-02-02