Supervisor 后台进程管理

img

Author:rab



前言

Supervisor 是一个进程控制系统,基于 Python 开发的一个 client/server 服务,它允许其用户监控和控制类 UNIX 操作系统上的许多进程(不支持 Windows 系统)。能将一个普通的命令行进程变为后台 daemon,并监控进程状态,异常退出时能自动重启。

用 Supervisor 管理的进程,当一个进程意外被杀死,Supervisort 监听到进程死后,会自动将它重新拉起,很方便的做到进程自动恢复的功能,不再需要自己写 shell 脚本来控制。

官方参考文档

一、安装

常用三种安装方法:yum、pip、easy_install。接下来以 CentOS 7.9 为例,分别介绍安装步骤。

1.1 Yum

1、安装 Supervisor

yum install -y epel* && yum install -y supervisor

2、启动 Supervisor 并做开机自启动

systemctl start supervisord.service
systemctl enable supervisord.service

3、验证 Supervisor 版本

[root@supervisor ~]# supervisord -v
3.4.0

1.2 Pip

1、安装 Python3.x

image-20220807130748498

没有 3.9 版本的 Python,想要安装更高版本的话,可通过编译安装。

image-20220807132147612

但是 Python 3.6 是可以安装的,对于 Surprise 安装该版本即可。

yum install -y python36

image-20220807132450838

2、安装 Supervisor

使用 pip 来安装,前提要保证 pip 版本大于 2.6

pip3.6 install supervisor

1.3 easy_install

easy_install-3.6 supervisor

二、配置

2.1 常用命令

supervisorctl status                    // 查看所有进程的状态
supervisorctl status es                 // 查看指定进程的状态
supervisorctl start|stop|restart all    // 对所有进程操作
supervisorctl stop es                   // 停止es
supervisorctl start es                  // 启动es
supervisorctl restart es                // 重启es
supervisorctl update                    // 配置文件修改后使用该命令加载新的配置
supervisorctl reload                    // 重新启动配置中的所有程序

2.2 配置文件

安装好后在/etc/会生成一个 supervisord.conf 文件及一个 supervisord.d 文件目录。

supervisord.d 目录用来存放用户自定义的进程配置。

1、看看 supervisord.conf 配置文件内容

image-20220807134516088

; Sample supervisor config file.

[unix_http_server]
file=/var/run/supervisor/supervisor.sock   ; (the path to the socket file)
;chmod=0700                 ; sockef 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]         ; 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=/var/log/supervisor/supervisord.log  ; (main log file;default $CWD/supervisord.log)
logfile_maxbytes=50MB       ; (max main logfile bytes b4 rotation;default 50MB)
logfile_backups=10          ; (num of main logfile rotation backups;default 10)
loglevel=info               ; (log level;default info; others: debug,warn,trace)
pidfile=/var/run/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 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:///var/run/supervisor/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 http_username if set
;password=123                ; should be same as http_password if set
;prompt=mysupervisor         ; cmd line prompt (default "supervisor")
;history_file=~/.sc_history  ; use readline history if available

; The below sample program section 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)
;autorestart=true              ; retstart at unexpected quit (default: true)
;startsecs=10                  ; number of secs prog must stay running (def. 1)
;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 b4 SIGKILL (default 10)
;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 (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 (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 below sample eventlistener section shows all possible
; eventlistener subsection values, create one or more 'real'
; eventlistener: sections to be able to handle event notifications
; sent by supervisor.

;[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)
;autorestart=unexpected        ; restart at unexpected quit (default: unexpected)
;startsecs=10                  ; number of secs prog must stay running (def. 1)
;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 b4 SIGKILL (default 10)
;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 (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        ; # of stderr logfile backups (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 below sample group section 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 = supervisord.d/*.ini

2、说明

配置文件中看 [include] 部分,在该部分中,我们可以自定义应用程序管理配置,配置文件名以 *.ini 结尾,当然,你也可以根据自己的习惯来文件名,如files = supervisord.d/*.conf

三、实践

3.1 ES 服务

以 ES 为例进行 Supervisor 功能验证。

3.1.1 服务部署

1、安装 ES

执行安装脚本(略)

image-20220807140726605

2、验证 ES

[root@supervisor elasticsearch]# lsof -i:9200 
COMMAND  PID USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
java    1698 yyds  121u  IPv6  23984      0t0  TCP *:wap-wsp (LISTEN)

image-20220807141552973

3.1.2 Supervisor 管理应用程序

1、新增 Supervisor 自定义配置

用于管理 ES 的生命周期

vim /etc/supervisord.d/es.ini
[program:es]
command=/data/elasticsearch/bin/elasticsearch
directory=/data/elasticsearch
user=yyds
numprocs=1
priority=1
autostart=true
startsecs=30
satrtretries=3
autorestart=true
stopasgroup=true
killasgroup=true
redirect_stderr=true
stdout_logfile_maxbytes=10MB
stdout_logfile_backups=10
stdout_logfile=/data/elasticsearch/logs/supervisor.log

# 注意:command 后面是启动命令,不能写成后台方式启动,如:nohup java -jar xxx.jar & 否则无法启动

2、在上面 ES 安装中,已经启动 ES 了,为效果先 kill 掉

image-20220807143255024

3、启动服务

supervisord -c /etc/supervisord.conf

4、看看状态

[root@supervisor ~]# supervisorctl status es
es                               RUNNING   pid 1269, uptime 0:01:46

此时,如果你的服务器重启了,supervisor 管理的进程会随服务器的重启而重启,前提是你本身的 supervisord 做了开机自启动。

3.2 Java 应用程序

3.2.1 构建 jar 测试包

image-20220807165005055

3.2.2 Supervisor 管理应用程序

1、新增配置文件

[program:java-test]
command=java -jar /root/java_code/target/springboot-test-1.0-SNAPSHOT.jar
directory=/root/java_code/target
user=root
numprocs=1
priority=1
autostart=true
startsecs=30
satrtretries=3
autorestart=true
stopasgroup=true
killasgroup=true
redirect_stderr=true
stdout_logfile_maxbytes=10MB
stdout_logfile_backups=10
stdout_logfile=/root/java_code/logs/supervisor.log

2、重载配置文件

supervisorctl reload

3、验证

image-20220807170420085

去浏览器访问:http://192.168.56.120:8080/test/

image-20220807170523509

3.3 启用 web 管理

具备 Python 环境

1、打开 HTTP web 字段注释

vim /etc/supervisord.conf

# 定义IP:PORT
# 定义用户名/密码
# 重载一下配置
# 注意端口不要与系统已有端口冲突

image-20220807171118227

2、重载配置

supervisorctl reload

3、web 验证

  • 登录

    image-20220807171534194

  • 看看管理界面

    image-20220807172336066

  • 可进行相关的点击操作

    刷新、停止(所有)、重启(所有)、查看日志、清理日志

    image-20220807174752093

  • 查看日志

    image-20220807172422599

四、Supervisord 对比 Systemd

首先,Supervisord 是 Python 写的一个守护进程,在 Linux 中(yum安装的 Supervisord)它本身也是由 Systemd 来管理。

而且 Systemd 也可以实现后台守护进程,稳定性相对于 Supervisor 要强,但是 Supervisord 具有统一进程管理的优势,同时也具备 Web 终端管理,实现进程的一键式管理。如果重启 Supervisord ,那 Supervisord 管理的整个进程也要被重启,对于 Systemd 来说,一个进程对应一个 Systemd 后台管理,而且是 Linux 原生的后台守护进程。

以下为 Systemd 后台管理进程的一个案例,其实现效果等同于 Supervisord。

vim /usr/lib/systemd/system/java-test.service
[Unit]
Description=java-test project service
Requires=network.target

[Service]
#User=root
#Group=root
Type=simple
WorkingDirectory=/root/java_code/target
ExecStart=/usr/bin/java -jar /root/java_code/target/springboot-test-1.0-SNAPSHOT.jar > /dev/null 2>&1
ExecStop=/bin/kill -s HUP $MAINPID

Restart=always
RestartSec=30
StartLimitInterval=30

[Install]
WantedBy=multi-user.target graphical.target

重载 systemd

systemctl daemon-reload

启动 Java 进程

# 启动
systemctl start java-test.service

# 开机自启
systemctl enable java-test.service

五、FAQ

5.1 加载 supervisor 配置报错

1、报错现象

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.
For help, use /usr/bin/supervisord -h

2、解决方案

# 找到sock文件并unlink或找到PID并kill掉 pe -ef |grep supervisord
[root@supervisor logs]# find / -name supervisor.sock
/run/supervisor/supervisor.sock

# unlink 或 kill
[root@supervisor logs]# unlink /run/supervisor/supervisor.sock

# 再次加载
[root@supervisor logs]# supervisord -c /etc/supervisord.conf

# 再或者重启supervisor
systemctl restart supervisord.service

image-20220807144149207

image-20220807144232368

5.2 supervisor 启动太快

1、报错现象

[root@supervisor ~]# supervisorctl status
es                               FATAL     Exited too quickly (process log may have details)

面向百度了一下,说把 startsecs 值设置为 0。

[program:es]
command=/data/elasticsearch/bin/elasticsearch
directory=/data/elasticsearch
user=yyds
numprocs=1
priority=1
autostart=true
startsecs=0
satrtretries=3
autorestart=true
stopasgroup=true
killasgroup=true
redirect_stderr=true
stdout_logfile_maxbytes=10MB
stdout_logfile_backups=10
stdout_logfile=/data/elasticsearch/logs/supervisor.log

好,重启后,确实变为 RUNNING 了

[root@supervisor ~]# supervisorctl status
es                               RUNNING   pid 22768, uptime 0:00:00

但是,并没什么 R 用,ES 进程并没有起来。

image-20220807150127308

在看看 supervisor.log 日志。

image-20220807145717858

提示:没有找到 Java 环境。

2、解决方案

为什么一开始却是执行成功的呢?而我重启服务器后就说无法找到 JAVA 环境呢?安装日志输出内容,JAVA 路径必须为/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin

# 先来看看我本机的 JDK 路径
[root@supervisor elasticsearch]# which java
/opt/jdk/bin/java

# 与日志输出的路径不一致,导致supervisor找不到JDK环境,从而导致ES无法运行,因为ES依赖于JDK

重新修改一下 JDK 二进制路径

[root@supervisor elasticsearch]# rm -rf /etc/profile.d/jdk.sh 
[root@supervisor elasticsearch]# source /etc/profile

做软链接,再次查看 JDK 路径

[root@supervisor elasticsearch]# ln -s /opt/jdk/bin/* /usr/bin/

image-20220807151301211

重启后还报错

image-20220807151923123

而我本机已经设置了最大文件打开数了啊

[root@supervisor logs]# ulimit  -H -n
65536

在看看 Supervisor 默认的配置文件,因该就是配置文件默认值的问题

image-20220807160210727

该值不能超过你操作系统本身的文件大小,于是将该值设置为 65536

image-20220807160437074

然后再次重启 Supervisor

image-20220807160558812

看看 ES 进程

image-20220807160646239

<点击跳转至开头>

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

云计算-Security

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值