V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
Distributions
Ubuntu
Fedora
CentOS
中文资源站
网易开源镜像站
xiaohantx
V2EX  ›  Linux

如何让任务每 a-b 分钟执行一次脚本

  •  
  •   xiaohantx ·
    xiaohantx · 2020-09-15 14:17:36 +08:00 · 3895 次点击
    这是一个创建于 1532 天前的主题,其中的信息可能已经有所发展或是发生改变。

    */8 * * * * /bin/sh /www/wwwroot/xxxx.com/crontab.sh

    目前是 8 分钟一次

    rand_num=$(($RANDOM%300+60))
    
    declare -i i=1;
    
    while ((i<rand_num))
    do
    	sleep 1
    	let i++
    done
    
    php /www/wwwroot/xxx.com/run.php
    
    

    每 8 分钟把任务提出来一次然后再延迟 1-5 分钟,但是这样就会出现两个任务在跑的情况。。。想单任务但是时间在 a-b 间任意

    34 条回复    2020-09-16 14:43:21 +08:00
    TaxKiz
        1
    TaxKiz  
       2020-09-15 14:35:30 +08:00
    #!/bin/bash

    export PATH='/bin:/sbin:/usr/bin:/usr/sbin'

    while true; do

    ps -ef | grep '/www/wwwroot/xxx.com/run.php' | grep -v '\bgrep\b' >/dev/null 2>&1

    if [$? != 0]; then

    rand_num=$(($RANDOM % 300 + 60))

    declare -i i=1

    while ((i < rand_num)); do
    sleep 1
    let i++
    done

    php /www/wwwroot/xxx.com/run.php

    unset -v rand_num i

    fi

    done
    xiaohantx
        2
    xiaohantx  
    OP
       2020-09-15 14:37:16 +08:00
    @TaxKiz crontab -e 里面的基础 8 分钟不变还是放在那是嘛
    xiaohantx
        3
    xiaohantx  
    OP
       2020-09-15 14:41:52 +08:00
    @TaxKiz 好像丢服务器线程跑满了,CPU 变成了 100%。。。
    TaxKiz
        4
    TaxKiz  
       2020-09-15 14:48:19 +08:00   ❤️ 1
    @xiaohantx 草率了,你加个 sleep

    ...
    unset -v rand_num i

    fi

    sleep 1

    done
    TaxKiz
        5
    TaxKiz  
       2020-09-15 14:48:50 +08:00   ❤️ 1
    @xiaohantx sleep 时间自己定义
    knightdf
        6
    knightdf  
       2020-09-15 15:00:23 +08:00   ❤️ 1
    ```shell
    */a * * * * python -c 'import random; import time; time.sleep(random.randint(0, b-a) * 60)' && flock -x -n /www/wwwroot/xxx.com/run.php php /www/wwwroot/xxx.com/run.php
    ```
    xiaohantx
        7
    xiaohantx  
    OP
       2020-09-15 15:02:46 +08:00
    @TaxKiz 不好意思不是很会 shell
    日志报了个错
    `/www/server/cron/d4e8c583cbd42140a85eac6baabec0f5: line 12: [1: command not found`

    另外想问下我已经配置了定时任务,每 N (固定)分钟执行这个脚本,脚本里面的 sleep 是啥意思= =比如 1 分钟执行了这个 4 次然后随机时间还没到在后台定时这时候 sleep 是起到什么作用呢,不过感谢老哥
    zlowly
        8
    zlowly  
       2020-09-15 15:04:21 +08:00   ❤️ 1
    1 、可以在脚本里保证单实例执行,大概方式就是
    a)判断如果 lock 文件是否存在,如果存在则退出
    b)touch lock
    c)用 trap 在 exit 时候 rm lock
    2 、这个需求其实还是不很明确,就是如果上一次还没执行完就到下一次的预定时间了该办?
    3 、可以不用 crontab,用 atd 服务,然后脚本末尾用 at 指定下次执行时间。
    xiaohantx
        9
    xiaohantx  
    OP
       2020-09-15 15:09:30 +08:00
    @knightdf 是要写进 crontab 嘛,我直接 shell 脚本跑返回了
    ```
    /www/server/cron/d4e8c583cbd42140a85eac6baabec0f5: line 4: */1: No such file or directory
    ----------------------------------------------------------------------------
    ★[2020-09-15 15:08:19] Successful
    ----------------------------------------------------------------------------
    ```
    knightdf
        10
    knightdf  
       2020-09-15 15:10:54 +08:00
    @xiaohantx 这是一条 cron 啊
    TaxKiz
        11
    TaxKiz  
       2020-09-15 15:15:10 +08:00   ❤️ 1
    ```sh
    #!/bin/bash

    export PATH='/bin:/sbin:/usr/bin:/usr/sbin'

    # 替换成实际路径
    P='/xxx/run.php'

    while true; do

    # 检测进程是否存在
    ps -ef | grep $P | grep -v '\bgrep\b' >/dev/null 2>&1

    # 如果进程不存在, 执行 PHP 脚本
    if [ $? != '0' ]; then

    rand_num=$(($RANDOM % 300 + 60))

    declare -i i=1

    while ((i < rand_num)); do
    sleep 1
    let i++
    done

    php $P

    unset -v rand_num i

    fi

    # 每 1 秒检测一次进程, 可自定义
    sleep 1

    done
    ```

    @xiaohantx
    xiaohantx
        12
    xiaohantx  
    OP
       2020-09-15 15:42:34 +08:00
    @knightdf 我是应该运行 crontab -e 然后粘贴进去嘛,然后 service crond restart 是嘛
    knightdf
        13
    knightdf  
       2020-09-15 15:44:16 +08:00   ❤️ 1
    @xiaohantx 参数做相应的更改后直接粘贴进去,不需要 restart
    xiaohantx
        14
    xiaohantx  
    OP
       2020-09-15 15:47:02 +08:00
    @TaxKiz sleep 我暂时没改默认的 1,rand_num=$(($RANDOM % 480 + 180))改为 2-8 分钟,但是输出还是一分钟一次,对了我这里试着用了宝塔的定时任务,定时执行时间是 1 分钟一次,不知道有没有影响
    xiaohantx
        15
    xiaohantx  
    OP
       2020-09-15 15:56:50 +08:00
    @knightdf
    */1 * * * * python -c 'import random; import time; time.sleep(random.randint(0, 2-1) * 60)' && flock -x -n /www/wwwroot/xxx.com/run.php php /www/wwwroot/xxx.com/run.php
    粘贴进去了好像会同时运行两次?理解的是这个时间 1 分钟基础时间然后随机 1-2 分钟,就是最快应该 2 分钟以上吧 2-3 分钟?
    xiaohantx
        16
    xiaohantx  
    OP
       2020-09-15 15:57:48 +08:00
    @knightdf 我注意到了,因为做的消息推送,每次发送,好像是发送完之后马上跟着再执行一次推送
    knightdf
        17
    knightdf  
       2020-09-15 16:15:40 +08:00
    @xiaohantx 不可能同时运行 2 次,这是一分钟一次,延迟 0 或者 1 分钟
    dier
        18
    dier  
       2020-09-15 16:19:15 +08:00
    declare -i s_number # 将变量声明为整数
    s_number=`cat /dev/urandom | tr -dc 1-6 | head -c 1`*60 # 随机出 1-5 之间的数乘以 60,得到秒数
    sleep $s_number # 睡眠指定秒数
    wait # 等待上面的命令执行完,即睡眠指定秒数再往下执行

    上面的放在你要执行的脚本前,触发定时任务后就会自动随机睡眠 1-5 分钟再执行
    xiaohantx
        19
    xiaohantx  
    OP
       2020-09-15 16:20:42 +08:00
    @knightdf 那还是之前那个原因嘛,每 1 分钟一次,比如一个 a 任务 3 分钟,b 任务 2 分钟,那第一个还没到时间 b 先执行了,然后 a 又执行了,但是这样应该也间隔一分钟吧.....有点懵,基础时间可以去掉嘛,只想给个区间时间,然后随机在这个区间进行执行任务
    treblex
        20
    treblex  
       2020-09-15 17:02:22 +08:00
    装个宝塔,或者 php 可以访问的话 直接用 url 监控
    xiaohantx
        21
    xiaohantx  
    OP
       2020-09-15 17:04:20 +08:00
    @dier emmm 那还是是会有个睡眠时间的增加吧。。类似于延迟,没办法稍微精准点控制,比如我想 3-8 分钟运行一次,没办法稍微精准点控制在范围内吗
    xiaohantx
        22
    xiaohantx  
    OP
       2020-09-15 17:05:32 +08:00
    @suke971219 宝塔的定时任务试固定的
    knightdf
        23
    knightdf  
       2020-09-15 17:32:52 +08:00
    @xiaohantx 你自己先把需求描述清楚吧
    mikurasa
        24
    mikurasa  
       2020-09-15 17:37:14 +08:00
    可以基于 cron 表达式+随机时间因子 和锁自己手写一个调度
    dier
        25
    dier  
       2020-09-15 17:42:07 +08:00
    @xiaohantx 你要求的就不是一个精确时间,怎么精准控制呢?要么 3 分钟,要么 8 分钟,你得确定执行间隔时间呀
    dier
        26
    dier  
       2020-09-15 17:53:09 +08:00   ❤️ 1
    想到了一个办法,不用睡眠等待,手动把定时任务写到 /etc/crontab 文件中,然后在你的脚本最后加上一段替换脚本,执行完脚本去更新这个文件中的间隔时间
    chogath
        27
    chogath  
       2020-09-15 20:35:54 +08:00
    短时间执行的可不可以考虑使用 延时队列呢? Redis 或者 MQ
    MagicalE
        28
    MagicalE  
       2020-09-15 21:23:04 +08:00
    是怕定时推送被检测嘛?
    xiaohantx
        29
    xiaohantx  
    OP
       2020-09-15 21:26:07 +08:00
    @MagicalE 是的 app 抓包的
    MagicalE
        30
    MagicalE  
       2020-09-15 23:12:59 +08:00
    @xiaohantx 我最近也在做类似功能,一个比较简单的 selenium 定时回复程序,定时执行总是被系统删除。

    windows 下只知道可以用计算机管理里面的基本任务来定时执行脚本,而那个基本任务的触发器必须指定具体时间,很头疼≡(▔﹏▔)≡
    ety001
        31
    ety001  
       2020-09-15 23:39:19 +08:00
    想要保证 crontab 单任务的话,可以试试 flock 给要执行的程序加锁。
    ety001
        32
    ety001  
       2020-09-15 23:41:38 +08:00
    随机时间放在 php 程序的开头,进入先 sleep 一个随机数,再执行。
    jinhan13789991
        33
    jinhan13789991  
       2020-09-16 09:39:02 +08:00
    简单,定时器执行任务脚本。脚本最后加上如下逻辑:删除定时器,再写入一个新的执行当前脚本的任务,执行时间是 a-b 分钟之后。
    more1sec
        34
    more1sec  
       2020-09-16 14:43:21 +08:00
    python 的 adscheduler 可以指定一个 cron 同时只能有 1 个实例在跑
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1025 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 20:09 · PVG 04:09 · LAX 12:09 · JFK 15:09
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.