前言:很早就想寫篇關於supervisor這個后台任務管理工具了,工作中也一直在用到,但是也只是簡單的參數復制復制,這次想把官方文檔重要的地方翻譯一下,然后結合自己實際工作的例子結合演示
官方文檔地址: http://supervisord.org/introduction.html#overview
原地址: https://blog.csdn.net/wgPython/article/details/103743321 現在已經遷移過來
一.Supervisor 介紹
首先介紹下supervisor是什么:
原文:Supervisor is a client/server system that allows its users to control a number of processes on UNIX-like operating systems
翻譯:supervisor是一個客戶端/服務端系統,它允許用戶在類Unix系統上控制多個進程
白話:說白了就是在Linux/Mac os等類Unix系統上管理后台任務進程的。
把程序放在后台執行,不至於關掉控制台,程序就不執行了。
注意
:supervisor是不支持Windows系統
的,原話Supervisor will not run at all under any version of Windows.
同樣的功能,Linux也有命令也有把程序放到后台運行的方式
- setsid
// 用法
setsid command
// 例如
setsid /home/xxx.sh
或者
setsid python a.py
- nohup
// 最簡單用法 還可以輸出日志等 (意思是把`command`命令啟動的服務托管到后台,然后把輸出內容保存到app.log里面)
nohup command > app.log 2>&1 &
盡管有這么多后台運行方式,但是功能和可靠性是沒有supervisor強大的。
http://supervisord.org/introduction.html#features
比如我所需要的,異常退出重啟,日志輸出管理,多任務進程等等
還可以自定義web控制面板監控
二.安裝篇
由於supervisor是Python寫的,所以需要依賴Python環境: Supervisor is intended to work on Python 3 version 3.4 or later and on Python 2 version 2.7.
Python3版本>=3.4 或者 Python2.7版本
類Unix系統一般是默認安裝了Python2.7的,所以可以直接用pip(Python包管理工具)安裝
# centos系統可以使用yum安裝
sudo yum install supervisor
# 或者pip在線安裝 ⚠️直接默認全局安裝Python2環境
pip install supervisor
# 或者pip離線包安裝 這里不介紹
相關文件說明
/etc/supervisord.conf # supervisord配置文件,一般不用設置
/etc/supervisord.d/ # 任務配置文件目錄,需要管理的后台任務得放在這個文件夾下,且文件后綴得以ini結尾
# 可以去 /etc/supervisord.conf 配置最后一行修改讀取配置文件的后綴
后台運行服務
# 啟動
sudo service supervisord start
# 重啟
sudo systemctl restart supervisord
# 有次我程序一直記載啟動異常,報錯不記得了,就是啟動不了我的任務
我搜到了關於解決我那個問題解決方式:
https://github.com/Supervisor/supervisor/issues/121#issuecomment-25202472
三.使用
e.g. 部署Flask 應用來做例子, 順便介紹下gunicorn的使用
我比較喜歡以這種方式部署:gunicorn + nginx + supervisor來部署
簡單介紹下gunicorn
比如我新建一個文件叫 wsgi.py (tip:名字可自己隨意取)
from flask import Flask
application = Flask(__name__) # 我就故意不取變量名為 app
@application.route('/')
def hello_world():
return 'Hello, World!'
if __name__ == '__main__':
application.run()
然后我用gunicorn服務的啟動命令就是, (注意我使用的是pipenv包管理)
pipenv run gunicorn --workers=4 --bind=0.0.0.0:8000 wsgi:application
參數 | 解釋 |
---|---|
--workers=4: | 可簡寫成-w=4 表示4個worker,可根據服務器配置調高 |
--bind=0.0.0.0:8000 | 可簡寫-b=ip:port 指定ip和端口,寫成0.0.0.0就可以外網通過ip訪問(一般寫成127.0.0.1, 由nginx轉發) 默認127.0.0.0:8000 |
wsgi:application | 表示wsgi表示應用文件名,application 表示應用里面取的對象名 |
正篇使用
使用supervisor管理 gunicorn 應用。(盡管gunicorn 參數-D可以托管到后台)
# 切換目錄
cd /etc/supervisord.d/
# 新建后台任務文件 如 flask.ini # 必須得以ini結尾
[program:app] ; app表示任務名稱,在后面supervisor控制面板里面會看到
command=pipenv run gunicorn app:app -w 8 ; 執行的程序命令
directory=/home/project ; 程序文件目錄
startsecs = 5 ; 啟動 5 秒后沒有異常退出,就當作已經正常啟動了
autorestart = true ; 程序異常退出后自動重啟
autostart=true ; supervisord 啟動的時候也自動啟動
;environment=變量名1="變量值1",變量名2="變量值2" ; 設置環境變量
;user=root ; 執行的任務的用戶,可不用指定
redirect_stderr=true
stdout_logfile=/home/project/logs/app.log # 自定義的輸出日志文件, 默認50M,多了會自動分割文件
- .ini注意配置文件最好不要加注釋, 如圖這是一個gunicorn 啟動配置示例:(取的絕對路徑)
[program:flask]
command=/root/.local/share/virtualenvs/xxx-zoz4Kxle/bin/gunicorn app:app -w 8
directory=/xxx/project
autostart=true
autorestart=true
stopsignal=QUIT
redirect_stderr=true
stdout_logfile=/xxx/project/logs/flask.log
- 還可以參考 Flask 狗書作者miguelgrinberg的github配置示例 https://github.com/miguelgrinberg/microblog/blob/master/deployment/supervisor/microblog.conf
- 有一種情況: 比如我同一個命令,要執行多次;
好比我使用的 rq https://github.com/rq/rq 這個簡單的消息隊列, 我要在一個服務器上啟多個服務,所以就直接開多個進程就行了。
# 直接在參數里面加這幾行
process_name=%(program_name)s_%(process_num)02d ;多進程名稱設置不同
numprocs=4 ;同時啟動多個進程
stopasgroup=true # 一起kill掉子進程
killasgroup=true # 多個進程一起kill
四 管理supervisor子任務
可以使用 supervisorctl
命令在控制面板查看當前運行的任務
# 控制面板操作
supervisor> restart app # 重啟任務 app任務名, 任務文件.ini中設置的 [program:app]
supervisor> stop app # 停止任務
supervisor> update app # 啟動app
supervisor> status app # 查看狀態
supervisor> exit # 退出
supervisor> help # 一共這么多命令
default commands (type help <topic>):
=====================================
add clear fg open quit remove restart start stop update
avail exit maintail pid reload reread shutdown status tail version
- 也可以在命令行運行
# 比如你在 /etc/supervisord.d/ 目錄下
先增加了一個flask.ini任務,
后面又新增scrapy.ini 任務
# 可以在命令行使用 update更新子任務
> sudo supervisorctl update # 默認更新全部 后面加 任務文件名 啟動特定任務