写点什么

高效复制:在 Linux 中并发执行相同任务,各自生成日志

  • 2023-04-12
    广东
  • 本文字数:2627 字

    阅读完需:约 9 分钟

高效复制:在Linux中并发执行相同任务,各自生成日志

业务爸爸的需求


需求:有个跑批任务 /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
复制代码


发布于: 刚刚阅读数: 4
用户头像

还未添加个人签名 2018-12-12 加入

还未添加个人简介

评论

发布
暂无评论
高效复制:在Linux中并发执行相同任务,各自生成日志_小毛驴的烂笔头_InfoQ写作社区