简单方便的linux定时任务管理器——supervisor

背景

我们在linux服务器上部署模型或者一个长期运行的程序的时候,通常使用的是nohup方法,因为nohup真的非常简单,只需要一行命令即可,但是nohup不好的地方就在于无法监控,并且无法自动中断重启,如果我们要查看一个nohup的程序是否在运行,需要每次输入ps -aux | grep "运城程序"才可以,比较繁琐,因此这里就推荐超好用的supervisor定时管理服务,并介绍一下他的核心用法,可以轻松上手

初次安装

由于supervisor在服务器上已经安装好了,等下次有机会自己安装的时候再更新~

3步完成部署

首先介绍一下supervisor的安装路径,通常会安装在/etc/下面,在/etc/supervisord.conf文件的最下面,我们可以看到supervisor的加载文件路径,这个路径是可以更改的

[include]
files =/etc/supervisord.d/*.ini

知道加载文件的路径后,咱们就可以开始部署程序了

  1. 编写.ini文件,格式如下
[program:deploy]
process_name=%(program_name)s
command=  /home/venv/bin/python  /home/python/deploy_api.py
directory= /home/python/
environment=PYTHONPATH=/home/
stdout_logfile=/home/logs/deploy.log
stderr_logfile=/home/logs/deploy.log
numprocs=1
numprocs_start=0
autostart=true
autorestart=true
  • program: deploy,这里的deploy决定了在supervisor中显示的名字,不同与其他重名
  • command: 第一个命令为python所在目录,第二个命令为想要运行的程序(这是以python进行距离,如果是java等其他一样)
  • directory: 项目目录,不一定非得是运行程序的上级
  • enviroment: 在这里是python环境的上级,anaconda也是类似的
  • stdout_logfile: 是输出的记录
  • stderr_logfile: 是错误的记录
  • numprocs: 运行的进程数
  • numprocs_start: 开始进程的编号
  • autostart: 是否自动启动
  • autorestart: 是否自动重启
  1. 在写.ini文件保存后,我们可以直接在centos上运行supervisorctl update进行更新,在ubuntu上可能得加上sudo
  2. 然后我们在命令行上输入supervisorctl就可以看到咱们的程序名字出现了,如果显示RUNNING那就代表程序正常运行了

注意点

  1. ini文件中最好不要写中文注释,可能会导致ini文件无法运行
  2. 要使用对应环境的python去运行,ini文件必须写对,不然会出现spawn error

其他语法

  1. sudo supervisorctl shutdown可以关闭supervisor
  2. 重启命令sudo supervisord -c /etc/supervisord.conf
  3. sudo supervisorctl reload重新加载所有supervisor定时命令,在多人合作时最好不要用
  4. supervisorctl命令行中,输入status刷新状态

需要控制环境变量时

在某些时候,我们运行python程序时,需要控制系统环境变量,例如:
LD_PRELOAD=./jemalloc-5.3.0/lib/libjemalloc.so python app.py
这种情况下,supervisor中的command便不能直接将环境变量加在前面,这种情况我们可以写一个shell脚本

LD_PRELOAD=/home/deploy/ps/workdir/jemalloc-5.3.0/lib/libjemalloc.so /home/deploy/anaconda3/envs/torch/bin/python /home/deploy/ps/workdir/deploy_api.py

然后将.ini文件的command改成
command=bash run_image_feature_api.sh

2023.4.26 更新

  1. 这次在ubuntu服务器上配置supervisor,踩了很多坑,首先是文件的目录位置是不一样的,与centos配置文件保存在/etc/supervisord.d/中不同,ubuntu是保存在/etc/supervisor/conf.d/,并且配置文件的后缀为.conf而并非是.ini
  2. unix:///var/run/supervisor.sock no such file,这个是缺少文件,需要创建sudo touch /var/run/supervisor.sock,同时需要赋予修改权限,sudo chmod 777 /var/run/supervisor.sock
  3. unknown error making dispatchers for ‘etcd‘: EACCES,这个问题是成功运行supervisord之后,运行sudo supervisorctl出现的,其原因是因为log文件没有修改权限导致的,因此我们需要对log文件增加权限,找到配置文件中设定的stderr文件和stdout文件所在位置,运行sudo chmod 777 log_files就可以了

2024.2.22更新

本次重启服务器,又遇到了unix:///var/run/supervisor.sock no such file问题,这次使用sudo service supervisord restart便解决了问题

为什么使用PHP管理crontab 一般在定时任务较少的情况下,使用原生的crontab服务一般不会有什么问题,但当定时任务较多时就会产生如下问题: 文本形式的定时任务可读性很差,在没有任何注释的情况下,新人很难在不读源码的情况下了解定时任务的业务逻辑 在分布式的场景中,定时任务会散落到多台机器上,无法统一管理 定时任务的日志不能集中化管理,对定时任务的运行分析及故障排除比较麻烦 基于以上几点原因,我们迫切的需要一个可以集中化管理的、可配置的定时任务管理器 但自己开发一套分布式的定时任务系统何其复杂,所以作者采用crontab服务做辅助,使用php实现对定时任务的配置管理 使用php管理定时任务有哪些优势 定时任务可以不再是以文本方式的形式存在,可以存储在缓冲、数据库中,甚至你可以开发管理功能,在后台对定时任务进行编辑 定时任务的日志是可配置的,你可以按照业务需求,对日志进行差异化配置 使用方式如下: 编写一个任务管理器,可参考test/simple.php 将上述脚本添加到crontab中,一分钟执行一次 示例: <?php $crontab_config = [  'test_1' => [  'name' => '服务监控1',  'cmd' => 'php -v',  'output' => '/tmp/test.log',  'time' => '* * * * *'  ],  'single_test' => [  'name' => 'php -i',  'cmd' => 'php -i',  'output' => '/tmp/single_script.log',  'time' => [  '* * * * *',  '* * * * *',  ],  ], ];  $crontab_server = new \Jenner\Zebra\Crontab\Crontab($crontab_config); $crontab_server->start(); 工具短小,但很精悍 在分布式场景中,你可以把定时任务写入数据库中进行统一管理,你可以设定哪些定时任务是由哪些机器执行, 然后通过生成文本文件的方式发送到所有机器上,再由这些机器上的phpCrontab读取处理;从而实现分布式场景下的定时任务统一管理。 标签:Zebra
### 使用 `gunicorn_config.py` 配置 Gunicorn 定时自动重启 为了使 Gunicorn 能够定时自动重启,可以利用 Python 的内置模块如 `signal` 和 `os` 来编写自定义逻辑并将其集成到 `gunicorn_config.py` 文件中。然而更推荐的方式是借助外部工具比如 Supervisor 或者 Linux 的 cron 作业来定期发送信号给 Gunicorn 进程触发其平滑重启。 #### 方法一:通过修改 `gunicorn_config.py` 可以在 `gunicorn_config.py` 中加入一段代码用于监听特定时间间隔后执行重载操作: ```python import signal import time from threading import Timer def restart_on_timer(): """Restart worker processes after a set interval.""" def kill_worker(signum, frame): raise KeyboardInterrupt # Set the timer to trigger every hour (3600 seconds) t = Timer(3600.0, lambda: os.kill(os.getpid(), signal.SIGUSR1)) t.daemon = True t.start() ``` 这段脚本会在每个小时结束时向当前工作进程发送 SIGUSR1 信号从而引起一次优雅的重启[^1]。 需要注意的是这种方法可能并不适用于所有的应用场景,并且可能会带来一些复杂度上的增加。因此建议考虑下面介绍的方法二作为替代方案。 #### 方法二:使用 Supervisord 实现定时重启 Supervisord 可以很方便地管理和监控多个守护程序,包括但不限于 Gunicorn 应用实例。通过配置 supervisord.conf 文件中的 eventlistener 插件配合事件通知机制能够轻松达成目的: ```ini [eventlistener:autorestart] command=while true; do sleep 3600 && supervisorctl restart gunicorn_app_name ; done events=TICK_60 stdout_logfile=/var/log/supervisor/autorestart.log stderr_logfile=/var/log/supervisor/autorestart_err.log ``` 上述配置使得 Supervisord 每隔一个小时就会尝试重新启动名为 "gunicorn_app_name" 的应用程序[^3]。 此方式不仅简单易懂而且稳定性更高,同时也便于维护人员理解和排查问题所在。 #### 方法三:利用 Cron Job 执行计划任务 对于那些不希望引入额外依赖的服务来说,还可以直接创建一个简单的 shell script 并安排它按照预定的时间表运行: ```bash #!/bin/bash sudo systemctl restart gunicorn.service ``` 接着编辑 crontab (`crontab -e`) 添加如下条目让该脚本每天凌晨两点钟被执行: ``` 0 2 * * * /path/to/restart_gunicorn.sh >> /dev/null 2>&1 ``` 这种方式同样有效但也存在局限性——即无法感知实际的工作负载状态就强制进行了重启动作[^4]。 综上所述,虽然可以通过调整 `gunicorn_config.py` 来实现这一功能,但从实践角度来看,采用 Supervisord 或 Crontab 等成熟解决方案往往更为合理可靠。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值