supervisor - Python進程管理工具(轉)


add by zhj: 下面是在ubuntu上的一些使用經驗

 

1. 簡介

supervisor有兩個組件:supervisord和supervisorctl,組成了client/server結構。

supervisord負責讀入配置文件,然后supervisord監管的應用程序以supervisord子進程的方式啟動,supervisord會自動將應用程序的進程轉為守護進程,

這樣即使你退出shell也沒影響。注意,如果一個進程已經是守護進程了,那用supervisord監控時,會出錯。

supervisorctl則負責和supervisord進行溝通,獲取運行中的進程信息,包含pid,uptime等信息。supervisorctl既可以通過命令行參數進行控制,又能夠

直接進入一個特有的shell,通過這個shell管控進程組。這樣,既能夠讓部分同學准確把握進程狀況,又能避免放開shell權限,一舉多得。

 

2. 安裝和配置

官網: http://www.supervisord.org/

建議用sudo pip install supervisor來安裝,不要用apt-get安裝

安裝后,用echo_supervisord_conf > ~/supervisord.conf生成配置文件

 

3. 啟動和關閉

啟動supervisor: supervisord -c /etc/supervisor/supervisor.conf   # 如果不指定配置文件,那自動加載/etc/supervisord.conf

一般會配置成開機自啟動,所以需要一個init腳本,參見Running supervisord automatically on startup,下載對應你的操作系統的啟動腳本就可以了,

不過,里面的內容可能需要修改,比如supervisord和supervisorctl的路徑,pid和log的路徑與你supervisord.conf中的pid和log路徑要相同

關閉supervisor: sudo kill <supervisord進程id>          # kill默然會發送SIGTERM信號,supervisord收到該信號會,會關閉所有子進程,最后關閉自己,這個過程可能需要幾秒鍾

 

4. 配置文件

詳細的配置參見http://www.cnblogs.com/ajianbeyourself/p/5534737.html

supervisord要求監控的進程不能是守護進程。比如要監控nginx,那你要在nginx配置文件nginx.conf中,設置daemon off

supervisor的配置項有很多,下面是公司dev環境上的celery_beat應用程序的配置項

[program:celery_beat]
command=python manage.py celery beat --loglevel=info --settings=configs.dev
directory=/home/zhj/work/hera/   ; 執行command前,先跳轉到directory
autorestart=true          ; 當進程關閉后,重啟,當然,對於用supervisorctl stop xx關閉的進程,不會重啟
redirect_stderr=true      ; 重定向程序的標准錯誤到標准輸出 (default false) startsecs=10 ; 啟動后堅持運行多長時間被認為是啟動成功了, (def. 1) stopwaitsecs=30 ; 最長結束等待時間,超過這個時間還沒收到子進程的SIGCHLD信號,那就用SIGKILL強制結束子進程 (default 10) stdout_logfile=/var/log/celery/celery_beat.log stdout_logfile_maxbytes=50MB autostart=true ; 當supervisor啟動后,也隨之啟動

5. supervisorctl命令

貌似只有啟動supervisor時,用到supervisord命令,其實情況下,用supervisorctl就可以了。

用下面的命令進入supervisor shell, sudo最好加上,不然有可能報錯

執行supervisorctl時,配置文件的搜索路徑如下

 

  1. $CWD/supervisord.conf
  2. $CWD/etc/supervisord.conf
  3. /etc/supervisord.conf

 

zhj@pc:~$ supervisorctl -c /etc/supervisor/supervisord.conf 
celery_beat                      STOPPED   Not started
celeryworker_celery:0            STOPPED   Not started
celeryworker_celery:1            STOPPED   Not started
celeryworker_email               STOPPED   Not started
supervisor> help

default commands (type help <topic>):
=====================================
add    exit      open  reload  restart   start   tail   
avail  fg        pid   remove  shutdown  status  update 
clear  maintail  quit  reread  signal    stop    version

supervisor> help start
start <name>        Start a process
start <gname>:*        Start all processes in a group
start <name> <name>    Start multiple processes or groups
start all        Start all processes
supervisor> 

下面是supervisorctl命令行下的命令:

status  #查看supervisord監控的所有進程的狀態

celery status  #查看celery進程的狀態

stop xxx   #停止某一個進程(xxx),xxx為[program:theprogramname]里配置的值

start xxx  #啟動某個進程

restart xxx  #重啟某個進程

stop groupworker  #重啟所

stop all  #停止全部進程,注:start有屬於名為groupworker這個分組的進程(start,restart同理)restartstop都不會載入最新的配置文件

reload   #重啟supervisor

update  #根據最新的配置文件,啟動新配置或有改動的進程,配置沒有改動的進程不會受影響而重啟。 當配置文件修改后,要執行這條命令。

                               #顯示用stop停止掉的進程,即使配置文件設置了autorestart=true,用reload或者update都不會自動重啟。

用supervisor監控celery和celery beat,配置參數見celery官方文檔提供的鏈接,

http://docs.celeryproject.org/en/latest/tutorials/daemonizing.html#supervisord

 

6. supervisor的log

  在[program:xxx]中,如果設置了numprocs > 1, 那每個進程會使用單獨的一個log文件,我們來分析下面的配置。

stdout和stderr文件都是/var/log/celery/celeryworker_celery.log

supervisor會啟動兩個celeryworker_celery進程(名稱分別是celeryworker_celery:0和celeryworker_celery:1),並在啟動時創建celeryworker_celery.log

還有celeryworker_celery.log.1 ~ celeryworker_celery.log.5這5個輪轉log文件。這兩個進程會分別寫不同的log文件,不會寫到同一個文件,

這是supervisor保證的。celeryworker_celery.log只會被其中一個進程使用,另一個進程會使用celeryworker_celery.log.xx。當celeryworker_celery.log

達到stdout_logfile_maxbytes時,它會被關閉,並重命名為celeryworker_celery.log.1,如果發現celeryworker_celery.log.1已經存在,那就把這

個已存在的celeryworker_celery.log.1重命名為celeryworker_celery.log.2,依次類推。你可以想象有多個水缸並排,在第一個水缸的頂部有一個注水

口,滿了之后,將水缸向右推一個位置,即推到第二個水缸的位置,然后在第一個水缸的位置增加一個新水缸,而最右邊的那個水缸被擠出隊列。一個注水

口就相當於一個進程,當numprocs>1,即多個進程時,就是在numprocs個水缸上面各有一個進水口。在

http://supervisord.org/configuration.html#program-x-section-settings的配置項`stdout_logfile`中提到It is not possible for two processes

to share a single log file (stdout_logfile) when rotation (stdout_logfile_maxbytes) is enabled. This will result in the file being corrupted. 

即當設置了log rotate時,supervisor可以保證每個進程使用不同的log文件

[program:celeryworker_celery]
command=python manage.py celery worker -l info -Q celery -c 1 --settings=configs.local_default
directory=/home/workspace/gikoo/
redirect_stderr=true                     ; 將stderr重定向到stdout
startsecs=10
stopwaitsecs=30
stdout_logfile=/var/log/celery/celeryworker_celery.log
stdout_logfile_maxbytes=3KB
autostart=false
autorestart=false
numprocs=2
process_name=%(process_num)d
stdout_logfile_backups=5

7. 遇到的一些問題

不知是什么原因,用supervisor監控celery worker時,有時會出現僵屍進程,每個celery worker都是一個進程池,

每個進程池有一個main process和一組worker process,每個main process都是supervisor的子進程。但使用中

發現,有時會出現一些celery進程的父進程是1號進程,當時沒有檢查這些進程是main process還是worker process,

猜想是worker process的可能性比較大,原因有可能是supervisor關閉celery時,main process在沒有等待worker 

process關閉的情況下就關閉了,這樣worker process就沒了父進程,1號進程就成了他們的父進程。由於任務的獲取

都是main process與broker之間進行的,這樣的話,那些1號進程下的worker process由於無法與broker通信,所以

也就不會再執行任務了(這塊東西待研究)。

 

原文:http://chenxiaoyu.org/2011/05/31/python-supervisor.html

經常會碰到要寫一些守護進程,簡單做法放入后台:

shell> nohup python xxx.py & 

偶爾這么做還可以接受,如果一堆這樣的呢?

當然還有一個問題,就是各種服務,對應的命令或者路徑都不太一致,比如Apache、MySQL或者其他自行編譯的工具。

如果可以統一管理這些應用,是不是很哈皮?

按照慣例現Google一把,不失所望找到一個神奇的利器。supervisor!

supervisor地址:http://supervisord.org,官方標語就是:一個進程管理工具。

安裝:

sudo pip install supervisor

安裝好以后,有兩個可執行文件和一個配置文件(平台差異,可能路徑不一致):

/usr/bin/supervisord -- supervisor服務守護進程 

/usr/bin/supervisorctl -- supervisor服務控制程序,比如:status/start/stop/restart/update

/etc/supervisor/supervisord.conf -- 配置文件,定義服務名稱以及接口等等

下面來一個示例,用web.py寫一個hello的程序:

import web
urls = (     '/(.*)','hello' ) 
app = web.application(urls, globals())
class hello:     
    def GET(self, name):         
        return 'hello: ' + name 

if __name__ == '__main__':     
    app.run() 

這個時候可以直接啟動這個程序了,下面來配置supervisor,加入管理。修改supervisord.conf,加入如下片段:

[program:hello]
command=python /home/smallfish/hello.py
autorstart=true
stdout_logfile=/home/smallfish/hello.log

上面的意思應該很容易懂,program后面跟服務的名稱,command是程序的執行路徑,autorstart是表示應用程序隨supervisor的啟動而啟動,stdout_logfile是捕獲標准輸出。

到這里,基本搞定了,下面就是啟動管理:

shell> sudo /etc/init.d/supervisor start   -- 啟動supervisor服務 
shell> sudo supervisorctl status hello     -- 獲取hello服務的狀態,因為是autorstart,這里已經啟動了 
hello  RUNNING    pid 1159, uptime :20:32 
shell> sudo supervisorctl stop hello       -- 停止hello服務 
hello: stopped 
shell> sudo supervisorctl stop hello       -- 再次停止hello,會有錯誤信息 hello: ERROR (not running) 
shell> sudo supervisorctl start hello      -- 啟動hello服務 hello: started 

OK,基本的操作就是類似這個了,仔細看supervisord.conf文件里會發現有一段[unix_http_server]的配置,默認是9001端口,可以輸入用戶名和密碼,主要用於Basic Auth認證用的。

填寫一下,然后重啟supervisor服務,打開瀏覽器輸入:http://localhost:9001,如圖:

sudo supervisorctl shutdown  # 關閉supervisord,會同時關閉supervisord監控的所有進程

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM