1. 程式人生 > 實用技巧 >Linux程序管理工具之Supervisor的使用

Linux程序管理工具之Supervisor的使用

Supervisor 的使用

一 Supervisor介紹

Supervisor (http://supervisord.org) 是一個用 [Python] 寫的程序管理工具,可以很方便的用來啟動、重啟、關閉程序(不僅僅是 Python 程序)。除了對單個程序的控制,還可以同時啟動、關閉多個程序,比如很不幸的伺服器出問題導致所有應用程式都被殺死,此時可以用 supervisor 同時啟動所有應用程式而不是一個一個地敲命令啟動

二 安裝

2.1 安裝方式

# 可以通過apt-get、yum安裝,既然Supervisor是基於python編寫的,那我們就用pip安裝好了

# 1 配置好yum源後,可以直接安裝
yum install supervisor

#2 Debian/Ubuntu可通過apt安裝
apt-get install supervisor

# 3 pip安裝
sudo yum install python-setuptools-devel
pip install supervisor

# 4 easy_install安裝
sudo yum install python-setuptools-devel
easy_install supervisor

2.2 驗證

# 1 安裝完成後,會在 /usr/bin 下加入三個命令:
[root@lqz bin]# ls |grep super
echo_supervisord_conf  # 生成一個配置檔案示例
supervisorctl          # 服務端
supervisord            # 客戶端
# 2 安裝完成後,會在 /etc 下建立一個 supervisord.d目錄用於存放supervisor的配置檔案,
# 還有一個supervisord.conf配置檔案(如果沒有使用命令: echo_supervisord_conf > /etc/supervisord.conf 生成)
[root@lqz etc]# ls |grep super
supervisord.conf
supervisord.d

# 3 方便起見,把supervisor伺服器相關的配置寫入supervisord.conf中,把監控各個程序的配置,按照程序名存在 supervisord.conf 目錄下。(這個可以在supervisord.conf中的[include]部分下配置)

2.3 配置

# 1 修改配置檔案
vim supervisord.conf 
# 2 最後一行改為(;表示註釋),這樣配置檔案可以寫到supervisord.d目錄下一xx.ini命名
[include]
files = supervisord.d/*.ini

# 3 簡單說明:
    [unix_http_server] 配置socket連線部分
    [supervisord] 配置supervisor伺服器部分
    [supervisorctl] 配置supervisor客戶端部分
    [inet_http_server] 配置web管理介面
    [include] 配置需要引入的其他配置

2.4 配置詳情(瞭解)

[unix_http_server]
file=/tmp/supervisor.sock   ; UNIX socket 檔案,supervisorctl 會使用
;chmod=0700                 ; socket 檔案的 mode,預設是 0700
;chown=nobody:nogroup       ; socket 檔案的 owner,格式: uid:gid

;[inet_http_server]         ; HTTP 伺服器,提供 web 管理介面
;port=127.0.0.1:9001        ; Web 管理後臺執行的 IP 和埠,如果開放到公網,需要注意安全性
;username=user              ; 登入管理後臺的使用者名稱
;password=123               ; 登入管理後臺的密碼

[supervisord]
logfile=/tmp/supervisord.log ; 日誌檔案,預設是 $CWD/supervisord.log
logfile_maxbytes=50MB        ; 日誌檔案大小,超出會 rotate,預設 50MB
logfile_backups=10           ; 日誌檔案保留備份數量預設 10
loglevel=info                ; 日誌級別,預設 info,其它: debug,warn,trace
pidfile=/tmp/supervisord.pid ; pid 檔案
nodaemon=false               ; 是否在前臺啟動,預設是 false,即以 daemon 的方式啟動
minfds=1024                  ; 可以開啟的檔案描述符的最小值,預設 1024
minprocs=200                 ; 可以開啟的程序數的最小值,預設 200

; the below section must remain in the config file for RPC
; (supervisorctl/web interface) to work, additional interfaces may be
; added by defining them in separate rpcinterface: sections
[rpcinterface:supervisor]
supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface

[supervisorctl]
serverurl=unix:///tmp/supervisor.sock ; 通過 UNIX socket 連線 supervisord,路徑與 unix_http_server 部分的 file 一致
;serverurl=http://127.0.0.1:9001 ; 通過 HTTP 的方式連線 supervisord

; 包含其他的配置檔案
[include]
files = relative/directory/*.ini    ; 可以是 *.conf 或 *.ini

2.5 啟動、停止、重啟

# 1 啟動supervisord
supervisord -c /etc/supervisord.conf   或  supervisord 
# 2 停止supervisord
supervisorctl shutdown
# 3 重新載入配置檔案
supervisorctl reload

# 4 注意:如果配置了密碼(使用如下命令)
supervisorctl -u user -p 123 reload

三 program 配置

# 只要在/etc/supervisord.d/目錄下所有 *.ini都會被管理
vi /etc/supervisord.d/redis.ini
[program:redis-server]
command=/usr/bin/redis-server /etc/redis/6379.conf
priority=999                ; 優先順序(越小越優先)
autostart=true              ; supervisord啟動時,該程式也啟動
autorestart=true            ; 異常退出時,自動啟動
startsecs=10                ; 啟動後持續10s後未發生異常,才表示啟動成功
startretries=3              ; 異常後,自動重啟次數
exitcodes=0,2               ; exit異常丟擲的是0、2時才認為是異常
stopsignal=QUIT             ; 殺程序的訊號

; 在程式傳送stopignal後,等待作業系統將SIGCHLD返回給supervisord的秒數。
; 如果在supervisord從程序接收到SIGCHLD之前經過了這個秒數,
; supervisord將嘗試用最終的SIGKILL殺死它
stopwaitsecs=1
user=root                   ; 設定啟動該程式的使用者
log_stdout=true             ; 如果為True,則記錄程式日誌
log_stderr=false            ; 如果為True,則記錄程式錯誤日誌
logfile=/var/log/redis-server.log    ; 程式日誌路徑
logfile_maxbytes=1MB        ; 日誌檔案最大大小
logfile_backups=10          ; 日誌檔案最大數量

四 程序管理

# 1啟動supervisord管理的所有程序
supervisorctl start all
#2 停止supervisord管理的所有程序
supervisorctl stop all
#3 啟動supervisord管理的某一個特定程序
supervisorctl start program-name   # program-name為[program:xx]中的xx
# 4 停止supervisord管理的某一個特定程序
supervisorctl stop program-name  // program-name為[program:xx]中的xx

# 5 重啟所有程序或所有程序
supervisorctl restart all 
# 重啟所有supervisorctl reatart program-name 
# 重啟某一程序,program-name為[program:xx]中的xx
# 6 檢視supervisord當前管理的所有程序的狀態
supervisorctl status

五 使用 supervisorctl 客戶端命令

#Supervisorctl 是 supervisord 的一個命令列客戶端工具,啟動時需要指定與 supervisord 使用同一份配置檔案,否則與 supervisord 一樣按照順序查詢配置檔案
supervisorctl -c /etc/supervisord.conf
# 上面這個命令會進入 supervisorctl 的 shell 介面,然後可以執行不同的命令了:

supervisorctl # 或者啟動後,直接使用 (進入shell介面)

> status    # 檢視程式狀態
> stop program-name    # 關閉 program-name  程式
> start program-name   # 啟動 program-name  程式
> restart program-name     # 重啟 program-name  程式
> reread    # 讀取有更新(增加)的配置檔案,不會啟動新新增的程式
> update    # 重啟配置檔案修改過的程式

上面這些命令都有相應的輸出,除了進入 supervisorctl 的 shell 介面,等同於直接在 bash 終端執行:
$ supervisorctl status
$ supervisorctl stop usercenter
$ supervisorctl start usercenter
$ supervisorctl restart usercenter
$ supervisorctl reread
$ supervisorctl update

六 使用web管理

# 1 修改配置檔案
vim /etc/supervisord.conf 
# 2 修改內容如下
[inet_http_server]         ; inet (TCP) server disabled by default
port=0.0.0.0: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))

# 3 重啟
supervisorctl reload
# 4 在瀏覽器開啟:http://101.133.225.166:8080/
可以看到

七 Supervisor配置systemctl服務,開機自動啟

# 1 新建配置檔案
vim  /usr/lib/systemd/system/supervisor.service
# 2 內容如下
[Unit]
Description=supervisor
After=network.target

[Service]
Type=forking
ExecStart=/usr/bin/supervisord -c /usr/local/supervisord.conf
ExecStop=/usr/bin/supervisorctl $OPTIONS shutdown
ExecReload=/usr/bin/supervisorctl $OPTIONS reload
KillMode=process
Restart=on-failure
RestartSec=42s

[Install]
WantedBy=multi-user.target

# 3 幹掉原先的supervisor程序
ps -ef|grep super
root     14465     1  0 00:58 ?        00:00:00 /usr/bin/python /usr/bin/supervisord -c /etc/supervisord.conf
kill 14465
#4 使用systemctl啟動
systemctl start supervisor.service
systemctl status supervisor.service
#5 開機自啟
systemctl enable supervisor.service

八 Supervisor管理redis和nginx

8.1 配置nginx

#1 vim /etc/vim /etc/supervisord.d/nginx.ini
# 2 寫入
[program:nginx]
command=/usr/sbin/nginx  -g 'daemon off;' 
autostart=true ; 自動啟動
autorestart=true ; 自動重啟
user=root ; 以哪個使用者執行
stdout_logfile=/tmp/supervisor_nginx.log ; 日誌路徑

8.2 配置redis

#1 vim /etc/vim /etc/supervisord.d/redis.ini
# 2 寫入
[program:redis]
command=redis-server 
autostart=true ; 自動啟動
autorestart=true ; 自動重啟
user=root ; 以哪個使用者執行
stdout_logfile=/tmp/supervisor_redis.log ; 日誌路徑

8.3 重啟

supervisorctl shutdown
supervisord -c /etc/supervisord.conf
# 或者
supervisorctl reload

8.4 測試

# 殺死nginx程序
# 殺死redis程序
redis-cli
輸入:shutwodn
# 發現服務又自動重啟了

九 常見問題及解決

9.1 問題一

# 報錯
BACKOFF   Exited too quickly (process log may have details)
# 原因
supervisor 比較適合監控業務應用,且只能監控前臺程式,實現的daemon【後臺啟動】的程式不能用它監控,否則supervisor> status 會提示:BACKOFF  Exited too quickly (process log may have details)

9.2 問題二

# 報錯
FATAL     Exited too quickly (process log may have details
# 原因
錯誤FATAL產生的原因可能是你的python命令的環境配置有問題,如果你是虛擬環境配置的話,必須使用虛擬環境的路徑的python或gunicorn命令否則會失敗!
# 解決
[program:gunicorn]
command=/root/.local/share/virtualenvs/blog/bin/gunicorn -c other_config/gunicorn.py main:app 
#; 這裡的gunicorn必須是你執行python環境對應的環境【如果是虛擬環境就必須配置虛擬環境的路徑下面的命令】
autostart = true     ; 在 supervisord 啟動的時候也自動啟動

9.3 問題三

# 報錯
啟動了多個supervisord服務,導致無法正常關閉服務
在執行supervisord -c /etc/supervisord.conf之前,直接執行過supervisord -c /etc/supervisord.d/xx.conf導致有些程序被多個superviord管理,無法正常關閉程序。
# 解決
使用ps -fe | grep supervisord檢視所有啟動過的supervisord服務,kill相關的程序。

9.4 問題四

# 報錯
unix:///var/run/supervisor/supervisor.sock no such file
# 解決
sudo chmod 777 /run
sudo chmod 777 /var/log

9.5 問題五

# 報錯
Unlinking stale socket /var/run/supervisor/supervisor.sock

# 解決(或者直接刪除)
unlink /var/run/supervisor/supervisor.sock

9.6 問題六

#報錯
Error: Another program is already listening on a port that one of our HTTP servers is configured to use.  Shut this program down first before starting supervisord.
# 解決
ps aux | grep supervisord
kill - 9 程序ID