业务爸爸的需求
需求:有个跑批任务 /data/wwwroot/cmd/OnlyOnceController.php,需要开通 n(>=3)个进程同时处理, 同时满足如下条件:
把日志重向到对应的日志文件如(out_[N].log, N 对应进程编号)
如果任务异常退出,并能拉起。(注意如果进程 3 拉起后,日志还要继续追加到之前的 out_3.log)
为了方便演示,我把有业务逻辑的php 程序,换成一个shell脚本,如下:
root@VM-ubuntu:/opt/tmp# cat tpl.shwhile true; do echo "$(date +'%Y-%m-%d %H:%M:%S')" sleep 10sdone
执行任务命令: nohup bash tpl.sh >> out_1.log &
复制代码
无脑脚本大法
思路如下: 由于重定向是在程序执行时进行的操作,ps 命令无法直接查看程序的重定向信息。所以为了满足上面要求的第二条,我们需要把脚本名设置成唯一的。如 tpl_1.sh.
# cat run.sh#!/bin/bash# author 小毛驴#
SHELL_DIR=$(cd $(dirname $0);pwd)cd ${SHELL_DIR}
# 任务数量NUM_TASKS=3
# 任务命令TASK_CMD_TPL="tpl.sh"
# 循环监控脚本的运行状态while true; do for ((i=1; i<=$NUM_TASKS; i++)); do # 检查任务是否已经在运行 echo ${TASK_CMD_TPL} if ! pgrep -f "${TASK_CMD_TPL}_$i" > /dev/null; then if [ ! -e ${TASK_CMD_TPL}_$i ]; then cp ${TASK_CMD_TPL} ${TASK_CMD_TPL}_$i chmod +x ${TASK_CMD_TPL}_$i fi nohup bash ${TASK_CMD_TPL}_$i >> out_$i.log & echo "Task ${TASK_CMD_TPL}_$i started." else echo "Task ${TASK_CMD_TPL}_$i is already running." fi done sleep 10done
复制代码
# lsnohup.out out_1.log out_2.log out_3.log run.sh tpl.sh tpl.sh_1 tpl.sh_2 tpl.sh_3# pgrep -f tpl.sh158551604316100# tail -f out*.log==> out_1.log <==2023-04-10 22:49:12
==> out_2.log <==2023-04-10 22:49:12
==> out_3.log <==2023-04-10 22:49:12
复制代码
虽然比较 low,但是功能也实现。注意为了防止 run.sh 意外退出,上面的 run.sh 脚本要放到 crontab 任务并加一个排它锁,或者称为写入锁。
有没有更好的方式呢?
那肯定是有的,我们之所以用 tpl.sh_1 tpl.sh_2 这些脚本,就是执行运行多个 tpl.sh 脚本后,如果其中一个挂掉,重新拉起,不能满足上述要求的第二条。如果每个脚本或者命令执行的时候都有一个唯一 id,基于这个 id 拉起对应的任务,那就解决要复制多个脚本的问题了。
给命令加一个唯一 id
command --unique-id xxxx 的方式,给每个脚本或者命令执行的时候指定一个唯一id。
复制代码
# cat unique-id.sh#!/bin/bash# author 小毛驴#
SHELL_DIR=$(cd $(dirname $0);pwd)cd ${SHELL_DIR}
# 任务数量NUM_TASKS=3
# 任务命令TASK_CMD_TPL="tpl.sh"
# 循环监控脚本的运行状态while true; do for ((i=1; i<=$NUM_TASKS; i++)); do # 检查任务是否已经在运行 # 此时检查的是 唯一id if ! pgrep -f "${TASK_CMD_TPL}_$i" > /dev/null; then nohup bash ${TASK_CMD_TPL} --unique-id "${TASK_CMD_TPL}_$i" >> out_$i.log & echo "Task ${TASK_CMD_TPL}_$i started." else echo "Task ${TASK_CMD_TPL}_$i is already running." fi done sleep 10done
复制代码
# nohup bash unique-id.sh &# ps -ef | grep tpl.shroot 22689 22675 0 23:03 pts/1 00:00:00 bash tpl.sh --unique-id tpl.sh_1root 22693 22675 0 23:03 pts/1 00:00:00 bash tpl.sh --unique-id tpl.sh_2root 22697 22675 0 23:03 pts/1 00:00:00 bash tpl.sh --unique-id tpl.sh_3# tail -f out*.log==> out_1.log <==2023-04-10 23:03:32
==> out_2.log <==2023-04-10 23:03:32
==> out_3.log <==2023-04-10 23:03:32
复制代码
交给专业工具
专业的工具做专业的事情,比如 supervisor
复制代码
root@VM-ubuntu:/etc/supervisor/conf.d# cat tpl.conf[program:tpl]process_name=%(program_name)s_%(process_num)02dcommand=bash /opt/tmp/tpl.shstderr_logfile=/opt/tmp/%(program_name)s_%(process_num)02d_err.logstdout_logfile=/opt/tmp/%(program_name)s_%(process_num)02d_out.logautostart=trueuser=rootautorestart=truestartretries=100startsecs=10numprocs=3
复制代码
root@VM-ubuntu:/etc/supervisor/conf.d# supervisorctlsupervisor> updatetpl: added process groupsupervisor> statustpl:tpl_00 RUNNING pid 27674, uptime 0:00:11tpl:tpl_01 RUNNING pid 27671, uptime 0:00:11tpl:tpl_02 RUNNING pid 27675, uptime 0:00:11
复制代码
root@VM-ubuntu:/etc/supervisor/conf.d# pgrep -f tpl.sh276712767427675root@VM-ubuntu:/etc/supervisor/conf.d# ps -ef | grep tpl.sh | grep -v "grep"root 27671 1410 0 23:14 ? 00:00:00 bash /opt/tmp/tpl.shroot 27674 1410 0 23:14 ? 00:00:00 bash /opt/tmp/tpl.shroot 27675 1410 0 23:14 ? 00:00:00 bash /opt/tmp/tpl.sh
# tail -f tpl_0*==> tpl_00_err.log <==
==> tpl_00_out.log <==2023-04-10 23:15:242023-04-10 23:15:342023-04-10 23:15:442023-04-10 23:15:54
==> tpl_01_err.log <==
==> tpl_01_out.log <==2023-04-10 23:15:242023-04-10 23:15:342023-04-10 23:15:442023-04-10 23:15:54
==> tpl_02_err.log <==
==> tpl_02_out.log <==2023-04-10 23:15:242023-04-10 23:15:342023-04-10 23:15:442023-04-10 23:15:54
复制代码
评论