jenkins结合supervisor进行python程序发布后的自动重启 项目背景: 通过jenkins发布kvaccount.chinasoft.com站点的python服务端程序,业务部门同事需要每次发布完成须后自动重启python服务端 具体执行中遇到的问题: 代码的目录是apache的属主权限,通过jenkins远程调用脚本,强制关闭服务进程,再次启动进程,发现程序能正常重启,但是会夯住,导致jenkins发布job没法结束,想到supervisor都能没有tty的情况下管理程序,于是安装supervisor进行进程的管理 脚本如下: 直接在终端下可以正常重启程序,在jenkins程序调用的时候就失效了,导致程序夯住 #--------------------------------------------- [root@:/data/www/vhosts/kvaccount.chinasoft.com/httpdocs/Source]# cat restart_kvaccount.sh #!/bin/bash # # kill fastcgi.py source /etc/profile py_num=`ps -ef|grep fastcgi.py|grep -v grep|wc -l` if [ $py_num -ge 1 ];then ps -ef|grep fastcgi.py|grep -v grep|awk '{print $2}'|xargs kill -9 fi # start it #su apache -c "cd /data/www/vhosts/kvaccount.chinasoft.com/httpdocs/Source && nohup python3 fastcgi.py > /dev/null &" cd /data/www/vhosts/kvaccount.chinasoft.com/httpdocs/Source && nohup python3 fastcgi.py > /dev/null & exit 0 #--------------------------------------------- 1.安装supervisor pip3 install supervisor cp /usr/local/python373/bin/supervisorctl /usr/bin/ cp /usr/local/python373/bin/supervisord /usr/bin/ 2.添加配置 mkdir -p /etc/supervisor/conf.d # 主配置supervisord.conf [root@srv3:/etc/supervisor/conf.d]# cat /etc/supervisor/supervisord.conf ; Sample supervisor config file. ; ; For more information on the config file, please see: ; http://supervisord.org/configuration.html ; ; Notes: ; - Shell expansion ("~" or "$HOME") is not supported. Environment ; variables can be expanded using this syntax: "%(ENV_HOME)s". ; - Quotes around values are not supported, except in the case of ; the environment= options as shown below. ; - Comments must have a leading space: "a=b ;comment" not "a=b;comment". ; - Command will be truncated if it looks like a config file comment, e.g. ; "command=bash -c 'foo ; bar'" will truncate to "command=bash -c 'foo ". [unix_http_server] ;file=/tmp/supervisor.sock ; the path to the socket file file=/etc/supervisor/conf.d/supervisor.sock ; the path to the socket file chmod=0700 ; socket file mode (default 0700) chown=apache:users ; socket file uid:gid owner ;username=user ; default is no username (open server) ;password=123 ; default is no password (open server) ;[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) [supervisord] logfile=/tmp/supervisord.log ; main log file; default $CWD/supervisord.log logfile_maxbytes=50MB ; max main logfile bytes b4 rotation; default 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 ; supervisord pidfile; default supervisord.pid nodaemon=false ; start in foreground if true; default 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 ; The supervisorctl section configures how supervisorctl will connect to ; supervisord. 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=unix:///etc/supervisor/conf.d/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 ; The sample program section below shows all possible program subsection values. ; 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) ; 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] files = conf.d/*.conf # 程序的守护程序配置 [root@srv3:/etc/supervisor/conf.d]# cat service-worker.conf [program:chinasoft-account] process_name=%(program_name)s_%(process_num)02d command=/usr/local/bin/python3 /data/www/vhosts/kvaccount.chinasoft.com/httpdocs/Source/fastcgi.py autostart=true autorestart=true user=apache numprocs=1 numprocs_start=1 redirect_stderr=true stdout_logfile=/tmp/chinasoft-account.log 3.启动supervisor程序 chown -R apache.users /etc/supervisor # 启动supervisor /usr/local/bin/python3 /usr/bin/supervisord -c /etc/supervisor/supervisord.conf -u apache 4.发布程序apache账号的ssh方式进行重启python程序脚本 # 发布代码后自动重启python的shell脚本 [root@srv3:/etc/supervisor/conf.d]# cat /data/www/vhosts/kvaccount.chinasoft.com/httpdocs/Source/restart_kvaccount.sh #!/bin/bash # # kill fastcgi.py #!/bin/sh source /etc/profile /usr/bin/supervisorctl restart chinasoft-account:* # python服务端相关程序和配置 [root@srv3:/data/www/vhosts/kvaccount.chinasoft.com/httpdocs/Source]# cat fastcgi.py from app import app from flup.server.fcgi import WSGIServer if __name__ == '__main__': WSGIServer(app,bindAddress=('127.0.0.1', 8008)).run() [root@srv3:/data/www/vhosts/kvaccount.chinasoft.com/httpdocs/Source]# cat /usr/local/nginx/conf/vhost.d/kvaccount.chinasoft.com.conf server { listen 80; server_name kvaccount.chinasoft.com; access_log on; access_log /data/www/logs/nginx_log/access/kvaccount.chinasoft.com_access.log main ; error_log /data/www/logs/nginx_log/error/kvaccount.chinasoft.com_error.log ; root /data/www/vhosts/kvaccount.chinasoft.com/httpdocs/Source; index index.html index.shtml index.php; #location / { # #include uwsgi_params; # #uwsgi_pass 127.0.0.1:8008; #} location / { # 指定 fastcgi 的主机和端口 fastcgi_pass 127.0.0.1:8008; fastcgi_param PATH_INFO $fastcgi_script_name; fastcgi_param REQUEST_METHOD $request_method; fastcgi_param QUERY_STRING $query_string; fastcgi_param CONTENT_TYPE $content_type; fastcgi_param CONTENT_LENGTH $content_length; fastcgi_param SERVER_PROTOCOL $server_protocol; fastcgi_param SERVER_PORT $server_port; fastcgi_param SERVER_NAME $server_name; fastcgi_pass_header Authorization; fastcgi_intercept_errors off; } location ^~ /logs { deny all; } } server { listen 443; ssl on; ssl_certificate cert2016/chinasoft_com.crt; ssl_certificate_key cert2016/chinasoft_com.key; ssl_dhparam cert2016/dh_2048.pem; ssl_session_timeout 5m; ssl_protocols TLSv1 TLSv1.1 TLSv1.2; ssl_ciphers "ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:!AES128-GCM-SHA256:!AES256-GCM-SHA384:!AES128-SHA256:!AES256-SHA256:!AES128-SHA:!AES256-SHA:AES:!CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA"; ssl_prefer_server_ciphers on; #ssl_stapling on; #ssl_stapling_verify on; server_name kvaccount.chinasoft.com ; access_log on; access_log /data/www/logs/nginx_log/access/kvaccount.chinasoft.com_access.log main ; error_log /data/www/logs/nginx_log/error/kvaccount.chinasoft.com_error.log ; root /data/www/vhosts/kvaccount.chinasoft.com/httpdocs/Source; index index.html index.shtml index.php ; error_page 404 403 /404.html; #location / { # #include uwsgi_params; # #uwsgi_pass 127.0.0.1:8008; #} location / { # 指定 fastcgi 的主机和端口 fastcgi_pass 127.0.0.1:8008; fastcgi_param PATH_INFO $fastcgi_script_name; fastcgi_param REQUEST_METHOD $request_method; fastcgi_param QUERY_STRING $query_string; fastcgi_param CONTENT_TYPE $content_type; fastcgi_param CONTENT_LENGTH $content_length; fastcgi_param SERVER_PROTOCOL $server_protocol; fastcgi_param SERVER_PORT $server_port; fastcgi_param SERVER_NAME $server_name; fastcgi_pass_header Authorization; fastcgi_intercept_errors off; } if ($http_user_agent ~ Ezooms) { return 403; } location ^~ /logs { deny all; } }