在項目中,常常有腳本須要常駐運行的需求。以PHP腳本爲例,最簡單的方式是:php
$ nohup php cli.php &
這樣能保證當前終端被關閉或者按CRTL+C後,腳本仍在後臺運行。可是無法保證腳本異常後自動重啓等。html
Supervisor 是用Python開發的一套通用的進程管理程序,能將一個普通的命令行進程變爲後臺daemon,並監控進程狀態,異常退出時能自動重啓。python
官網介紹:http://supervisord.org/linux
本文所用環境:git
引自官網(http://supervisord.org/introduction.html#platform-requirements):github
Supervisor已通過測試,能夠在Linux(Ubuntu 9.10),Mac OS X(10.4 / 10.5 / 10.6)和Solaris(10 for Intel)和FreeBSD 6.1上運行。它可能在大多數UNIX系統上都能正常工做。在任何版本的Windows下,Supervisor 都不會運行。Supervisor 可使用
Python 2.4
或更高版本,但不能在任何版本的Python 3
下使用。web
我使用的環境:docker
$ python -V Python 2.6.6
安裝方法有:
一、easy_install 安裝(需安裝有pip):瀏覽器
$ easy_install supervisor
二、pip 安裝(需安裝有pip,推薦):bash
$ pip install supervisor
三、Debian / Ubuntu能夠直接經過apt安裝:
$ apt-get install supervisor
本文測試的時候是使用pip安裝的。其它方式未作測試。
安裝後配置文件生成:
一、經過easy_install或pip安裝後,須要運行
$ mkdir /etc/supervisor $ echo_supervisord_conf > /etc/supervisor/supervisord.conf
生成配置文件。
二、使用apt-get
安裝後,supervisor的主配置文件在:
/etc/supervisor/supervisord.conf
supervisor的配置文件默認是不全的。子進程配置文件在:
/etc/supervisor/conf.d/*.conf
咱們先修改supervisord.conf
最後的[include]
部分配置:
[include] files = /etc/supervisor/conf.d/*.conf
這樣就能夠支持子配置文件,而不用改動主配置文件。
啓動方法通常有:
一、使用 pip
或者easy_install
安裝的supervisor
則:
$ supervisord
便可運行。
supervisor 默認在如下路徑查找配置文件:/usr/etc/supervisord.conf, /usr/supervisord.conf, supervisord.conf, etc/supervisord.conf, /etc/supervisord.conf, /etc/supervisor/supervisord.conf
如需指定主配置文件,則須要使用-c
參數:
$ supervisord -c /etc/supervisor/supervisord.conf
查看安裝的版本:
$ supervisord -v 3.3.4
而後查看supervisor的狀態:
$ supervisorctl status
注:
supervisord
是主進程,supervisorctl
是給守護進程發送命令的客戶端工具。
二、使用 apt-get
安裝的supervisor
直接能夠經過
$ /etc/init.d/supervisor start
運行。
咱們以簡單的 /tmp/echo_time.sh
爲例:
#/bin/bash while true; do echo `date +%Y-%m-%d,%H:%m:%s` sleep 2 done
在/etc/supervisor/conf.d/
新增子進程配置文件 echo_time.conf
:
[program:echo_time] command=sh /tmp/echo_time.sh priority=999 ; the relative start priority (default 999) autostart=true ; start at supervisord start (default: true) autorestart=true ; retstart at unexpected quit (default: true) startsecs=10 ; number of secs prog must stay running (def. 10) 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 before SIGKILL (default 10) user=root ; setuid to this UNIX account to run the program log_stdout=true log_stderr=true ; if true, log program stderr (def false) logfile=/tmp/echo_time.log logfile_maxbytes=1MB ; max # logfile bytes b4 rotation (default 50MB) logfile_backups=10 ; # of logfile backups (default 10) stdout_logfile_maxbytes=20MB ; stdout 日誌文件大小,默認 50MB stdout_logfile_backups=20 ; stdout 日誌文件備份數 stdout_logfile=/tmp/echo_time.stdout.log
而後啓動程序:
$ supervisorctl reread $ supervisorctl update
這兩個命令分別表明從新讀取配置、更新子進程組。執行update後輸出:
echo_time: added process group
這樣剛纔添加的echo_time
腳本就常駐運行起來了。能夠經過日誌查看運行狀況:
$ tail -f /tmp/echo_time.stdout.log 2018-12-22,14:12:1545459550 2018-12-22,14:12:1545459552 2018-12-22,14:12:1545459554
也可使用supervisorctl status
查看子進程運行狀況:
$ supervisorctl status echo_time RUNNING pid 28206, uptime 0:00:11
主配置文件名: supervisord.conf
能夠經過運行echo_supervisord_conf
得到。這個配置文件通常狀況下不須要更改,除了最後的[include]
部分,其他保持默認便可。
[unix_http_server] file=/tmp/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] ; 配置web後臺 ;port=127.0.0.1:9001 ; 指定ip_address:port, 使用 *:port 監聽全部 IP ;username=user ; 默認沒有用戶名 (open server) ;password=123 ; 默認沒有密碼 (open server) [supervisord] logfile=/tmp/supervisord.log ; 日誌文件; 默認 $CWD/supervisord.log logfile_maxbytes=50MB ; 日誌文件最大大小; 默認 50MB logfile_backups=10 ; # of main logfile backups; 0 means none, default 10 loglevel=info ; log level; default info; others: debug,warn,trace pidfile=/tmp/supervisord.pid ; pid文件 nodaemon=false ; 是否運行在前臺; 默認是後臺 minfds=1024 ; min. avail startup file descriptors; default 1024 minprocs=200 ; min. avail process descriptors;default 200 ;umask=022 ; process file creation umask; default 022 ;user=chrism ; default is current user, required if root ;identifier=supervisor ; supervisord identifier, default is 'supervisor' ;directory=/tmp ; default is not to cd during start ;nocleanup=true ; don't clean up tempfiles at start; default false ;childlogdir=/tmp ; 'AUTO' child log dir, default $TEMP ;environment=KEY="value" ; key value pairs to add to environment ;strip_ansi=false ; strip ansi escape codes in logs; def. false ; The rpcinterface:supervisor 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:x] sections. [rpcinterface:supervisor] supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface ; 配置 supervisorctl ; configure it match the settings in either the unix_http_server ; or inet_http_server section. [supervisorctl] serverurl=unix:///tmp/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 in [*_http_server] if set ;password=123 ; should be same as in [*_http_server] if set ;prompt=mysupervisor ; cmd line prompt (default "supervisor") ;history_file=~/.sc_history ; use readline history if available ; 下面是子進程配置文件示例 ; Create one or more 'real' program: sections to be able to control them under ; supervisor. ;[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) ;startsecs=1 ; # of secs prog must stay up to be running (def. 1) ;startretries=3 ; max # of serial start failures when starting (default 3) ;autorestart=unexpected ; when to restart if exited after running (def: unexpected) ;exitcodes=0,2 ; 'expected' exit codes used with autorestart (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 (0 means none, 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 (0 means none, 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) ; The sample eventlistener section below shows all possible eventlistener ; subsection values. Create one or more 'real' eventlistener: sections to be ; able to handle event notifications sent by supervisord. ;[eventlistener:theeventlistenername] ;command=/bin/eventlistener ; 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) ;events=EVENT ; event notif. types to subscribe to (req'd) ;buffer_size=10 ; event buffer queue size (default 10) ;directory=/tmp ; directory to cwd to before exec (def no cwd) ;umask=022 ; umask for process (default None) ;priority=-1 ; the relative start priority (default -1) ;autostart=true ; start at supervisord start (default: true) ;startsecs=1 ; # of secs prog must stay up to be running (def. 1) ;startretries=3 ; max # of serial start failures when starting (default 3) ;autorestart=unexpected ; autorestart if exited after running (def: unexpected) ;exitcodes=0,2 ; 'expected' exit codes used with autorestart (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=false ; redirect_stderr=true is not allowed for eventlisteners ;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 (0 means none, default 10) ;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 (0 means none, default 10) ;stderr_events_enabled=false ; emit events on stderr writes (default false) ;environment=A="1",B="2" ; process environment additions ;serverurl=AUTO ; override serverurl computation (childutils) ; The sample group section below shows all possible group values. Create one ; or more 'real' group: sections to create "heterogeneous" process groups. ;[group:thegroupname] ;programs=progname1,progname2 ; each refers to 'x' in [program:x] definitions ;priority=999 ; the relative start priority (default 999) ; 配置include files ; The [include] section can just contain the "files" setting. This ; setting can list multiple files (separated by whitespace or ; newlines). It can also contain wildcards. The filenames are ; interpreted as relative to this file. Included files *cannot* ; include files themselves. [include] ; .ini和.conf都支持 files = relative/directory/*.ini
通常放在:/etc/supervisor/conf.d/
目錄 。一個腳本對應一個配置文件。
配置說明:
;*爲必須填寫項 ;*[program:應用名稱] [program:cat] ;*命令路徑,若是使用python啓動的程序應該爲 python /home/test.py, ;不建議放入/home/user/, 對於非user用戶通常狀況下是不能訪問 command=/bin/cat ;當numprocs爲1時,process_name=%(program_name)s; 當numprocs>=2時,%(program_name)s_%(process_num)02d process_name=%(program_name)s ;進程數量 numprocs=1 ;執行目錄,如有/home/supervisor_test/test1.py ;將directory設置成/home/supervisor_test ;則command只需設置成python test1.py ;不然command必須設置成絕對執行目錄 directory=/tmp ;掩碼:--- -w- -w-, 轉換後rwx r-x w-x umask=022 ;優先級,值越高,最後啓動,最早被關閉,默認值999 priority=999 ;若是是true,當supervisor啓動時,程序將會自動啓動 autostart=true ;*自動重啓 autorestart=true ;啓動延時執行,默認1秒 startsecs=10 ;啓動嘗試次數,默認3次 startretries=3 ;當退出碼是0,2時,執行重啓,默認值0,2 exitcodes=0,2 ;中止信號,默認TERM ;中斷:INT(相似於Ctrl+C)(kill -INT pid),退出後會將寫文件或日誌(推薦) ;終止:TERM(kill -TERM pid) ;掛起:HUP(kill -HUP pid),注意與Ctrl+Z/kill -stop pid不一樣 ;從容中止:QUIT(kill -QUIT pid) ;KILL, USR1, USR2其餘見命令(kill -l),說明1 stopsignal=TERM stopwaitsecs=10 ;*以root用戶執行 user=root ;重定向 redirect_stderr=false stdout_logfile=/a/path stdout_logfile_maxbytes=1MB stdout_logfile_backups=10 stdout_capture_maxbytes=1MB stderr_logfile=/a/path stderr_logfile_maxbytes=1MB stderr_logfile_backups=10 stderr_capture_maxbytes=1MB ;環境變量設置 environment=A="1",B="2" serverurl=AUTO
簡化模板
[program:echo_time] command=sh /tmp/echo_time.sh autostart=true autorestart=true startsecs=10 startretries=3 exitcodes=0,2 stopsignal=QUIT stopwaitsecs=10 user=root log_stdout=true log_stderr=true logfile=/tmp/echo_time.log logfile_maxbytes=1MB logfile_backups=10 stdout_logfile_maxbytes=20MB stdout_logfile_backups=20 stdout_logfile=/tmp/echo_time.stdout.log
防盜版聲明:本文系原創文章,發佈於公衆號飛鴻影的博客
(fhyblog)及博客園,轉載需做者贊成。
supervisord 是主進程。
經過supervisord -h
能夠查看幫助說明。示例:
-c/--configuration FILENAME ;指定配置文件 -n/--nodaemon ;運行在前臺(調試用) -v/--version ;打印版本信息 -u/--user USER ;以指定用戶(或用戶ID)運行 -m/--umask UMASK ;指定子進程的umask,默認是022 -l/--logfile FILENAME ;指定日誌文件 -e/--loglevel LEVEL ;指定日誌級別
supervisorctl 是客戶端程序,用於向supervisord發起命令。
經過supervisorctl -h
能夠查看幫助說明。咱們主要關心的是其action
命令:
$ supervisorctl 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
這些命令對於控制子進程很是重要。示例:
reread ;從新加載配置文件 update ;將配置文件裏新增的子進程加入進程組,若是設置了autostart=true則會啓動新新增的子進程 status ;查看全部進程狀態 status <name> ;查看指定進程狀態 start all; 啓動全部子進程 start <name>; 啓動指定子進程 restart all; 重啓全部子進程 restart <name>; 重啓指定子進程 stop all; 中止全部子進程 stop <name>; 中止指定子進程 reload ;重啓supervisord add <name>; 添加子進程到進程組 reomve <name>; 從進程組移除子進程,須要先stop。注意:移除後,須要使用reread和update才能從新運行該進程
supervisord 有進程組(process group)的概念:只有子進程在進程組,才能被運行。
supervisorctl
也支持交互式命令行:
$ supervisorctl echo_time RUNNING pid 27188, uptime 0:05:09 supervisor> version 3.3.4 supervisor>
須要開啓supervisord.conf
註釋掉的這4行:
[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)
端口默認是監聽127.0.0.1:9001
,這裏方便測試,修改成:
port=*:9001
而後重啓主進程supervisord:
$ supervisorctl reload
瀏覽器訪問:http://myip:9001 ,輸入用戶名、密碼後,便可看到web頁面:
注意:若是修改配置文件時,
[inet_http_server]
這一行被註釋,會致使不只web須要認證,命令行使用supervisorctl
也須要認證,這時候就須要在交互式命令行裏輸入用戶名、密碼才能進行下一步的操做。
一、Centos6 docker環境沒有pip
解決方案:須要先安裝擴展源EPEL。
EPEL(http://fedoraproject.org/wiki/EPEL) 是由 Fedora 社區打造,爲 RHEL 及衍生髮行版如 CentOS、Scientific Linux 等提供高質量軟件包的項目。
首先安裝epel擴展源:
$ yum -y install epel-release
而後再安裝pip
$ yum -y install python-pip
查看版本:
$ pip -V pip 7.1.0 from /usr/lib/python2.6/site-packages (python 2.6)
參考:https://www.cnblogs.com/saolv/p/6963314.html
二、Centos6環境安裝supervisor
後,執行:
$ supervisor -V
出現:
Traceback (most recent call last): File "/usr/bin/echo_supervisord_conf", line 5, in <module> from pkg_resources import load_entry_point File "/usr/lib/python2.6/site-packages/setuptools-0.6c11-py2.6.egg/pkg_resources.py", line 2603, in <module> File "/usr/lib/python2.6/site-packages/setuptools-0.6c11-py2.6.egg/pkg_resources.py", line 666, in require File "/usr/lib/python2.6/site-packages/setuptools-0.6c11-py2.6.egg/pkg_resources.py", line 565, in resolve pkg_resources.DistributionNotFound: meld3>=0.6.5
緣由:pip安裝的meld3不可用,手動安裝。
wget https://pypi.python.org/packages/source/m/meld3/meld3-1.0.2.tar.gz tar -zxf meld3-1.0.2.tar.gz cd meld3-1.0.2 python setup.py install
感謝https://www.cnblogs.com/hubery/p/5653007.html 文章提供的方法!這個問題困擾了很久,github頁面(https://github.com/Supervisor/meld3/issues/23)提供的解決方案都不可行,反而致使pip都不能用了。
三、因參考github裏meld3解決方案致使pip不可用:
Traceback (most recent call last): File "/usr/bin/pip", line 5, in <module> from pkg_resources import load_entry_point File "/usr/lib/python2.6/site-packages/pkg_resources/__init__.py", line 957, in <module> class Environment: File "/usr/lib/python2.6/site-packages/pkg_resources/__init__.py", line 961, in Environment self, search_path=None, platform=get_supported_platform(), File "/usr/lib/python2.6/site-packages/pkg_resources/__init__.py", line 188, in get_supported_platform plat = get_build_platform() File "/usr/lib/python2.6/site-packages/pkg_resources/__init__.py", line 391, in get_build_platform from sysconfig import get_platform ImportError: No module named sysconfig
解決方案:刪除/site-packages
下面的包,從新安裝python-setuptools:
rm -rf /usr/lib/python2.6/site-packages/pkg_resources* yum reinstall python-setuptools
參考:https://stackoverflow.com/questions/50742538/importerror-no-module-named-sysconfig-cant-get-pip-working
四、輸入supervisord 命令後報錯:
Traceback (most recent call last): File "/usr/local/bin/supervisord", line 6, in <module> from pkg_resources import load_entry_point File "/usr/lib/python2.7/dist-packages/pkg_resources/__init__.py", line 3019, in <module> @_call_aside File "/usr/lib/python2.7/dist-packages/pkg_resources/__init__.py", line 3003, in _call_aside f(*args, **kwargs) File "/usr/lib/python2.7/dist-packages/pkg_resources/__init__.py", line 3032, in _initialize_master_working_set working_set = WorkingSet._build_master() File "/usr/lib/python2.7/dist-packages/pkg_resources/__init__.py", line 655, in _build_master ws.require(__requires__) File "/usr/lib/python2.7/dist-packages/pkg_resources/__init__.py", line 963, in require needed = self.resolve(parse_requirements(requirements)) File "/usr/lib/python2.7/dist-packages/pkg_resources/__init__.py", line 849, in resolve raise DistributionNotFound(req, requirers) pkg_resources.DistributionNotFound: The 'supervisor==3.2.0' distribution was not found and is required by the application
解決:
一、查找supervisord在哪
whereis supervisord
supervisord: /usr/local/bin/supervisord
二、執行
rm -rf /usr/local/bin/supervisord
緣由是supervisor 正常被卸載,supervisord 並無被正常卸載。
也能夠指定錯誤版本從新安裝:
pip install supervisor==3.2.0
詳情:https://hooklife.me/linux/Supervisor%E5%9C%A8deepin%E5%AE%89%E8%A3%85%E3%80%81%E5%8D%B8%E8%BD%BD%E4%B8%8E%E4%BD%BF%E7%94%A8/
一、Supervisor: A Process Control System — Supervisor 3.3.4 documentation http://supervisord.org/index.html 二、進程管理supervisor的簡單說明 - jyzhou - 博客園 https://www.cnblogs.com/zhoujinyi/p/6073705.html 三、DevOps https://mp.weixin.qq.com/s/mqrkAEaGFKJy-4PQadJJ9w? 四、supervisor使用 - 回首鄭板橋 - 博客園 https://www.cnblogs.com/hubery/p/5653007.html