程式管理程式supervisor安裝和使用

kingjian發表於2021-03-08

介紹

Supervisor是用Python開發的一套通用的程式管理程式,能將一個普通的命令列程式變為後臺daemon,並監控程式狀態,異常退出時能自動重啟

安裝方式

  • pip安裝
    pip install supervisor
    #安裝supervisor預設是沒有生成配置檔案的,生成配置檔案
    echo_supervisord_conf > /etc/supervisord.conf
  • yum安裝(推薦)
    #使用yum安裝supervisor
    yum install supervisor
    systemctl enable supervisord.service  
    安裝生成配置檔案,路徑/etc/supervisord.conf

laravel佇列demo

建立配置檔案

touch /etc/supervisord.d/www.laravel-vue.com.conf

配置

[program:www.laravel-vue.com]
process_name=%(program_name)s_%(process_num)02d
command=php /home/vagrant/code/app.laravel-vue.com/artisan queue:work --sleep=3 --tries=3
autostart=true
autorestart=true
user=root
numprocs=1
stopasgroup=true
killasgroup=true
redirect_stderr=true
stdout_logfile=/home/vagrant/code/app.laravel-vue.com/storage/logs/supervisor.log

配置項說明

 [program:www.laravel-vue.com]    ;監護程式名稱,唯一
 process_name=%(program_name)s_%(process_num)02d    ;程式名稱
 directory=/var/www/html/larabbs    ;命令執行的目錄
 command=php /home/vagrant/code/app.laravel-vue.com/artisan queue:work --sleep=3 --tries=3    ;要執行的命令
 autostart=true    ;當supervisor啟動時,程式自動啟動
 autorestart=true    ;自動重啟
 numprocs=1    ; 程式數
 user=root     ;執行命令的賬號
 stopasgroup=true    ;這個和下面一個配置可以防止監護的程式意外重啟後子程式殘留
 killasgroup=true redirect_stderr=true    ;這裡設為true,就可以配置下面的目錄
 stdout_logfile=/home/vagrant/code/app.laravel-vue.com/storage/logs/supervisor.log    ;日誌目錄

重啟服務:

#重新讀取配置
sudo supervisorctl reread
#更新配置
sudo supervisorctl update
#啟動
sudo supervisorctl start www.laravel-vue.com:*

配置檔案引數詳解

[unix_http_server]
file=/tmp/supervisor.sock   ;UNIX socket 檔案,supervisorctl用XML_RPC和supervisord通訊就是通過它進行,如果不設定的話,supervisorctl也就不能用了 
;chmod=0700                 ;socket檔案的mode(許可權),預設是0700
;chown=nobody:nogroup       ;socket檔案的owner(屬組),格式:uid:gid
;username=user              ;使用supervisorctl連線的時候,認證的使用者(預設沒有使用者名稱)
;password=123               ;和上面的使用者名稱對應的密碼,可以直接使用明碼,也可以使用SHA加密(預設沒有密碼)
;[inet_http_server]         ;偵聽在TCP上的socket,Web Server和遠端的supervisorctl都要用到它不設定的話,預設為不開啟。
;port=127.0.0.1:9001        ;這個是管理後臺執行的IP和埠,偵聽所有IP:9001*:9001。如果上面的[inet_http_server]開啟了,就必須設定它。如果開放到公網,需要注意安全性
;username=user              ;同上面的[unix_http_server]使用者名稱配置一致
;password=123               ;同上面的[unix_http_server]密碼配置一致
 [supervisord]            ;這個主要是定義supervisord這個服務端程式的一些引數的
logfile=/tmp/supervisord.log ;這個是supervisord這個主程式的日誌路徑,注意和子程式的日誌沒有關係。預設是 $CWD/supervisord.log,$CWD是當前目錄。
logfile_maxbytes=50MB        ;日誌檔案大小,預設50MB。超過50M的時候,會生成一個新的日誌檔案;如果設成0,表示不限制大小。
logfile_backups=10           ;日誌檔案保留備份數量預設10,設為0表示不備份
loglevel=info                ;日誌級別,預設info,其它: critical, error, warn, info, debug, trace, or blather
pidfile=/tmp/supervisord.pid ;pid 檔案
nodaemon=false               ;是否在前臺啟動,預設是false,即以 daemon 的方式啟動
minfds=1024                  ;可以開啟的檔案描述符的最小值,預設 1024,低於這個值supervisor將不會啟動。
minprocs=200                 ;可以開啟的程式數的最小值,預設200,低於這個值supervisor也將不會正常啟動。
;umask=022                   ;程式建立檔案的掩碼,預設為022;user=chrism                 ; 這個引數可以設定一個非root使用者,當我們以root使用者啟動supervisord之後。我這裡面設定的這個使用者,也可以對supervisord進行管理,預設情況是不設定。
;identifier=supervisor       ;這個引數是supervisord的識別符號,主要是給XML_RPC用的。當你有多個supervisor的時候,而且想呼叫XML_RPC統一管理,就需要為每個supervisor設定不同的識別符號,預設是supervisord。
;directory=/tmp              ;這個引數是當supervisord作為守護程式執行的時候,設定這個引數的話,啟動supervisord程式之前,會先切換到這個目錄預設不設定。
;nocleanup=true              ;這個引數當為false的時候,會在supervisord程式啟動的時候,把以前子程式產生的日誌檔案(路徑為AUTO的情況下)清除掉。有時候我們們想要看歷史日誌,當 然不想日誌被清除了。所以可以設定為true,預設是false,有除錯需求的同學可以設定為true;childlogdir=/tmp            ;當子程式日誌路徑為AUTO(系統自動分配)的時候,子程式日誌檔案的存放路徑。
;environment=KEY="value"     ;這個是用來設定環境變數的,supervisord在linux中啟動預設繼承了linux環境變數,在這裡可以設定supervisord程式特有的其他環境變數。supervisord啟動子程式時,子程式會拷貝父程式的記憶體空間內容。 所以設定的這些環境變數也會被子程式繼承。預設為不設定。
;strip_ansi=false            ;這個選項如果設定為true,會清除子程式日誌中的所有ANSI 序列。什麼是ANSI序列呢?就是我們的\n,\t這些東西。預設為false[supervisorctl]              ;這個主要是針對supervisorctl的一些配置  
serverurl=unix:///tmp/supervisor.sock ;通過UNIX socket連線supervisord,路徑與unix_http_server部分的file一致
;serverurl=http://127.0.0.1:9001 ; 通過HTTP的方式連線supervisord
;username=chris              ;使用者名稱,預設空
;password=123                ;密碼,預設空。
;prompt=mysupervisor         ;輸入使用者名稱密碼時候的提示,預設supervisor。                   
;history_file=~/.sc_history  ;這個引數和shell中的history類似,我們可以用上下鍵來查詢前面執行過的命令預設是no file的。所以我們想要有這種功能,必須指定一個檔案。

;[program:xx]             ;是被管理的程式配置引數,xx是程式的名稱
;command=/opt/apache-tomcat-8.0.35/bin/catalina.sh run  ;程式啟動命令;可以帶引數,如:/home/test.py -a 'hehe'有一點需要注意的是,我們的command只能是那種在終端執行的程式,不能是守護程式。這個想想也知道了,比如說command=service httpd start。httpd這個程式被linux的service管理了,我們的supervisor再去啟動這個命令,這已經不是嚴格意義的子程式了。
;directory=/tmp                ;程式執行前,會前切換到這個目錄
;autostart=true              ;在supervisord啟動的時候也自動啟動
;startsecs=10              ;啟動10秒後沒有異常退出,就表示程式正常啟動了,預設為1秒。
;autorestart=true          ;程式退出後自動重啟,可選值:[unexpected,true,false],預設為unexpected,表示程式意外殺死後才重啟
這個是設定子程式掛掉後自動重啟的情況,如果為false的時候,無論什麼情況下,都不會被重新啟動,如果為unexpected,只有當程式的退出碼不在下面的exitcodes裡面定義的退出碼的時候,才會被自動重啟。當為true的時候,只要子程式掛掉,將會被無條件的重啟。                               
;exitcodes=0,2               ;注意和上面的的autorestart=unexpected對應。exitcodes裡面的定義的退出碼是expected的。
;stopsignal=QUIT             ;程式停止訊號,可以為TERM, HUP, INT, QUIT, KILL, USR1, or USR2等訊號。預設為TERM 。當用設定的訊號去幹掉程式,退出碼會被認為是expected。    
;stopwaitsecs=10             ;這個是當我們向子程式傳送stopsignal訊號後,到系統返回資訊給supervisord,所等待的最大時間。 超過這個時間,supervisord會向該子程式傳送一個強制kill的訊號。 預設為10秒。
;startretries=3            ;啟動失敗自動重試次數,預設是3。當超過3次後,supervisor將把此程式的狀態置為FAIL
;user=tomcat               ;用哪個使用者啟動程式,預設是root。如果supervisord是root啟動,我們在這裡設定這個非root使用者,可以用來管理該program。
;priority=999              ;程式啟動優先順序,預設999,值小的優先啟動
;redirect_stderr=true ;把stderr重定向到stdout,預設false
;stdout_logfile_maxbytes=20MB ;stdout日誌檔案大小,預設50MB
;stdout_logfile_backups = 20  ;stdout日誌檔案備份數,預設是10
;stdout_logfile=/opt/apache-tomcat-8.0.35/logs/catalina.out ;程式的stdout的日誌路徑,可以指定路徑,AUTO,none等三個選項。設定為none的話,將沒有日誌產生。設定為AUTO的話,將隨機找一個地方生成日誌檔案,而且當supervisord重新啟動的時候,以前的日誌檔案會被清空。當 ;redirect_stderr=true的時候,sterr也會寫進這個日誌檔案。需要注意當指定目錄不存在時無法正常啟動,所以需要手動建立目錄(supervisord 會自動建立日誌檔案)
;stopasgroup=false         ;預設為false,程式被殺死時,是否向這個程式組傳送stop訊號,包括子程式。主要用於,supervisord管理的子程式,這個子程式本身還有子程式。那麼我們如果僅僅幹掉supervisord的子程式的話,子程式的子程式有可能會變成孤兒程式。所以我們們可以設定可個選項,把整個該子程式的整個程式組都幹掉。 設定為true的話,一般killasgroup也會被設定為true。需要注意的是,該選項傳送的是stop。預設為false;killasgroup=false             ;訊號預設為false,不過向程式組傳送的是kill訊號
;stderr_capture_maxbytes=1MB   ;這個一樣,和stdout_capture一樣。 預設為0,關閉狀態
;stderr_events_enabled=false   ;這個也是一樣,預設為false
;environment=A="1",B="2"       ;這個是該子程式的環境變數,和別的子程式是不共享的
;serverurl=AUTO    

;[group:thegroupname]  ;就是給programs(子程式)分組,劃分到組裡面的program。我們就不用一個一個去操作了,我們可以對組名進行統一的操作。 注意:program被劃分到組裡面之後,就相當於原來的配置從supervisor的配置檔案裡消失了。supervisor只會對組進行管理,而不再會對組裡面的單個program進行管理了
;programs=progname1,progname2 ;組成員,用逗號分開。
;priority=999                  ;優先順序,相對於組和組之間說的。預設999;包含其它配置檔案 ;當我們要管理的程式很多的時候,都寫在主配置檔案就不太合適了,這個時候可以把配置資訊寫到多個檔案中,然後include過來
[include]
files = relative/directory/*.ini    ;可以指定一個或多個以.ini結束的配置檔案

子程式demo

安裝的supervisor生成的預設配置檔案最後一行內容如下:

[include]
files = supervisord.d/*.ini

supervisor相關操作

  • 預設配置檔案啟動

    #預設去找/etc/supervisord.conf的配置檔案
    supervisord  
  • 指定配置檔案啟動

    supervisord -c /etc/supervisor/supervisord.conf    
  • 重啟supervisor

    supervisorctl reload   
  • 進入supervisor客戶端的互動終端

    supervisorctl
  • 啟動名字為blog的program

    supervisorctl start blog
  • 停止名字為blog的program

    supervisorctl stop blog
  • 檢視名字為django的program 狀態

    supervisorctl status blog
  • 檢視所有program的狀態

    supervisorctl status all
  • 啟動所有program

    supervisorctl start all
  • 停止所有program

    supervisorctl stop all
  • 檢視supervisorctl命令

    supervisorctl help 

    supervisord和supervisorctl

  • supervisord

    supervisord是supervisor的服務端程式。啟動supervisor程式自身,啟動supervisor管理的子程式,響應來自clients的請求,
    重啟閃退或異常退出的子程式,把子程式的stderr或stdout記錄到日誌檔案中,生成和處理Event。

  • supervisorctl

    如果說supervisord是supervisor的服務端程式,那麼supervisorctl就是client端程式了。
    supervisorctl有一個型別shell的命令列介面,可以利用它來檢視子程式狀態,啟動/停止/重啟子程式,
    獲取running子程式的列表等等。最重要的是,supervisorctl不僅可以連線到本機上的supervisord,
    還可以連線到遠端的supervisord,當然在本機上面是通過UNIX socket連線的,遠端是通過TCP socket連線的。
    supervisorctl和supervisord之間的通訊,是通過xml_rpc完成的。

使用過程中的問題

  • 問題一.Unlinking stale socket /var/run/supervisor/supervisor.sock
    解決方法:
    #執行
    unlink /var/run/supervisor/supervisor.sock
本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章