Python后端部署-Part3——Supervisor进程管理

[TOC]

nohup

  • 用途:不挂断地运行命令。

  • 语法:nohup Command [ Arg … ] [ & ]

    • Command:要执行的命令。
    • Arg:一些参数,可以指定输出文件。
    • &:让命令在后台执行,终端退出后命令仍旧执行。
  • 启动进程:

    • nohup python3 /data/WebService/backend/manage.py runserver 0.0.0.0:8000 >>/data/WebService/backend/log/output.log 2>&1 &
      
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12

      - 2>&1:将标准错误 2 重定向到标准输出 &1 ,标准输出 &1 再被重定向输入到 runoob.log 文件中。

      - 0 – stdin(standard input,标准输入)
      - 1 – stdout(standard output,标准输出)
      - 2 – stderr(standard error,标准错误输出)

      - 终止进程:

      - ```bash
      ps -aux | grep manage.py
      ps -aux | grep manage.py | grep -v grep | awk '{print $2}'
    • 参数说明:

      • a : 显示所有程序
      • u : 以用户为主的格式来显示
      • x : 显示所有程序,不区分终端机
    • ```bash
      kill -9 进程号PID

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15

      ## Supervisor

      ### 简介

      - Supervisor 是用 Python 开发的一套通用的进程管理程序,能将一个普通的命令行进程变为后台 daemon,并监控进程状态,异常退出时能自动重启。
      - 它是通过 fork/exec 的方式把这些被管理的进程当作 supervisor 的子进程来启动,这样只要在 supervisor 的配置文件中,把要管理的进程的可执行文件的路径写进去即可。也实现当子进程挂掉的时候,父进程可以准确获取子进程挂掉的信息的,可以选择是否自己启动和报警。
      - Supervisor 还提供了一个功能,可以为 supervisord 或者每个子进程,设置一个非 root 的 user,这个 user 就可以管理它对应的进程。

      ### 安装

      1. 配置好 yum 源后,可以直接安装

      ```bash
      yum install supervisor
  1. Debian/Ubuntu 可通过 apt 安装

    1
    apt-get install supervisor
  2. pip 安装

    1
    pip install supervisor

    配置文件

默认配置文件

  • 默认配置文件:/etc/supervisor/supervisord.conf(可能会在不同的地方)
  • 默认配置文件一般不需要改动,直接定义自己的配置文件即可
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
[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,如果设成0,表示不限制大小
logfile_backups=10 ;日志文件保留备份数量默认10,设为0表示不备份
loglevel=info ;日志级别,默认info,其它: debug,warn,trace
pidfile=/tmp/supervisord.pid ;pid 文件
nodaemon=false ;是否在前台启动,默认是false,即以 daemon 的方式启动
minfds=1024 ;可以打开的文件描述符的最小值,默认 1024
minprocs=200 ;可以打开的进程数的最小值,默认 200

[supervisorctl]
serverurl=unix:///tmp/supervisor.sock ;通过UNIX socket连接supervisord,路径与unix_http_server部分的file一致
;serverurl=http://127.0.0.1:9001 ; 通过HTTP的方式连接supervisord

; [program:xx]是被管理的进程配置参数,xx是进程的名称
[program:xx]
command=/opt/apache-tomcat-8.0.35/bin/catalina.sh run ; 程序启动命令
autostart=true ; 在supervisord启动的时候也自动启动
startsecs=10 ; 启动10秒后没有异常退出,就表示进程正常启动了,默认为1秒
autorestart=true ; 程序退出后自动重启,可选值:[unexpected,true,false],默认为unexpected,表示进程意外杀死后才重启
startretries=3 ; 启动失败自动重试次数,默认是3
user=tomcat ; 用哪个用户启动进程,默认是root
priority=999 ; 进程启动优先级,默认999,值小的优先启动
redirect_stderr=true ; 把stderr重定向到stdout,默认false
stdout_logfile_maxbytes=20MB ; stdout 日志文件大小,默认50MB
stdout_logfile_backups = 20 ; stdout 日志文件备份数,默认是10
; stdout 日志文件,需要注意当指定目录不存在时无法正常启动,所以需要手动创建目录(supervisord 会自动创建日志文件)
stdout_logfile=/opt/apache-tomcat-8.0.35/logs/catalina.out
stopasgroup=false ;默认为false,进程被杀死时,是否向这个进程组发送stop信号,包括子进程
killasgroup=false ;默认为false,向进程组发送kill信号,包括子进程

;包含其它配置文件
[include]
files = relative/directory/*.ini ;可以指定一个或多个以.ini结束的配置文件

自定义子进程配置文件(常用)

  • 自定义的子进程配置文件路径:/etc/supervisor/conf.d/
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# 项目名
[program:WebService]
# 脚本目录
directory=/data/WebService/backend
# 脚本执行命令
command=python3 /data/WebService/backend/manage.py runserver 0.0.0.0:8000
; command=uwsgi --ini /data/WebService/backend/start.ini

#supervisor启动的时候是否随着同时启动,默认True
autostart=true
# 当程序exit的时候,这个program不会自动重启,默认unexpected,设置子进程挂掉后自动重启的情况,
# 有三个选项,false,unexpected和true。
# 如果为false的时候,无论什么情况下,都不会被重新启动,
# 如果为unexpected,只有当进程的退出码不在下面的exitcodes里面定义的
autorestart=unexpected
# 这个选项是子进程启动多少秒之后,此时状态如果是running,则我们认为启动成功了。默认值为1
startsecs=1
# 脚本运行的用户身份
user = test
# 日志输出
stderr_logfile=/data/WebService/backend/log/web_err.log
stdout_logfile=/data/WebService/backend/log/web_out.log
# 把stderr重定向到stdout,默认 false
redirect_stderr = true
# stdout日志文件大小,默认 50MB
stdout_logfile_maxbytes = 50MB
# stdout日志文件备份数
stdout_logfile_backups = 20

注意:supervisor 不能监控后台进程,因此 command 不能为后台运行命令

启动服务

supervisord 直接启动

1
supervisord -c /etc/supervisor/supervisord.conf

systemctl 命令启动

  • 编辑配置文件
1
vim /usr/lib/systemd/system/supervisord.service
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[Unit]
Description=Supervisor daemon

[Service]
Type=forking
PIDFile=/home/supervisor/supervisord.pid
ExecStart=/usr/local/python3/bin/supervisord -c /etc/supervisord.conf
ExecStop=/usr/local/python3/bin/supervisorctl shutdown
ExecReload=/usr/local/python3/bin/supervisorctl reload
KillMode=process
Restart=on-failure
RestartSec=42s

[Install]
WantedBy=multi-user.target
  • 常用命令
1
2
3
4
5
systemctl stop supervisord
systemctl start supervisord
systemctl status supervisord
systemctl reload supervisord
systemctl restart supervisord

常用命令(常用)

  1. supervisorctl status all:查看所有进程的状态

  2. supervisorctl stop [program]:停止 program

    • program 换成 all 可以管理配置中的所有进程
  3. supervisorctl start [program]:启动 program

  4. supervisorctl restart [program]:重启 program

  5. supervisorctl update:配置文件修改后可以使用该命令加载新的配置

    • $ cp /data/WebService/backend/supervisor.conf /etc/supervisor/conf.d/supervisor.conf
      $ supervisorctl update
      WebService: added process group  # 其实这个时候已经开始运行后台了
      
      1
      2
      3
      4
      5
      6

      6. `supervisorctl reload`:重新启动 supervisor

      - ```bash
      $ supervisorctl reload
      Restarted supervisord
      ### 常见问题
  6. unix:///var/run/supervisor/supervisor.sock no such file

    • 没有开启服务。supervisord -c /etc/supervisor/supervisord.conf
  7. 启动了多个 supervisord 服务,导致无法正常关闭服务

    • 使用 ps -fe | grep supervisord 查看所有启动过的 supervisord 服务,kill 相关的进程 kill -9 进程号
  8. 启动 uwsgi 时要注释 uwsgi 里的如下配置,否则 supervisorctl 启动时会报错

    • ; daemonize = /home/apps/logManage/logs/uwsgi.log
      ; pidfile = /home/apps/logManage/conf/uwsgi.pid
      ; 可以增加 logto配置
      logto = /home/apps/logManage/logs/uwsgi.log  
  9. bind(): Address already in use [core/socket.c line 769]