技术解析

如何让任务每 a-b 分钟执行一次脚本
0
2021-06-16 15:45:32
idczone

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

目前是 8 分钟一次

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

declare -i i=1;

while ((i

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


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

crontab -e 里面的基础 8 分钟不变还是放在那是嘛

好像丢服务器线程跑满了,CPU 变成了 100%。。。

草率了,你加个 sleep
...
unset -v rand_num i
fi
sleep 1
done

sleep 时间自己定义

```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
```

不好意思不是很会 shell
日志报了个错
`/www/server/cron/d4e8c583cbd42140a85eac6baabec0f5: line 12: [1: command not found`
另外想问下我已经配置了定时任务,每 N (固定)分钟执行这个脚本,脚本里面的 sleep 是啥意思= =比如 1 分钟执行了这个 4 次然后随机时间还没到在后台定时这时候 sleep 是起到什么作用呢,不过感谢老哥

1 、可以在脚本里保证单实例执行,大概方式就是
a)判断如果 lock 文件是否存在,如果存在则退出
b)touch lock
c)用 trap 在 exit 时候 rm lock
2 、这个需求其实还是不很明确,就是如果上一次还没执行完就到下一次的预定时间了该办?
3 、可以不用 crontab,用 atd 服务,然后脚本末尾用 at 指定下次执行时间。

是要写进 crontab 嘛,我直接 shell 脚本跑返回了
```
/www/server/cron/d4e8c583cbd42140a85eac6baabec0f5: line 4: */1: No such file or directory
----------------------------------------------------------------------------
★[2020-09-15 15:08:19] Successful
----------------------------------------------------------------------------
```

这是一条 cron 啊

```sh
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

我是应该运行 crontab -e 然后粘贴进去嘛,然后 service crond restart 是嘛

参数做相应的更改后直接粘贴进去,不需要 restart

sleep 我暂时没改默认的 1,rand_num=$(($RANDOM % 480 + 180))改为 2-8 分钟,但是输出还是一分钟一次,对了我这里试着用了宝塔的定时任务,定时执行时间是 1 分钟一次,不知道有没有影响


*/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 分钟?

我注意到了,因为做的消息推送,每次发送,好像是发送完之后马上跟着再执行一次推送

不可能同时运行 2 次,这是一分钟一次,延迟 0 或者 1 分钟

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 分钟再执行

那还是之前那个原因嘛,每 1 分钟一次,比如一个 a 任务 3 分钟,b 任务 2 分钟,那第一个还没到时间 b 先执行了,然后 a 又执行了,但是这样应该也间隔一分钟吧.....有点懵,基础时间可以去掉嘛,只想给个区间时间,然后随机在这个区间进行执行任务

装个宝塔,或者 php 可以访问的话 直接用 url 监控

emmm 那还是是会有个睡眠时间的增加吧。。类似于延迟,没办法稍微精准点控制,比如我想 3-8 分钟运行一次,没办法稍微精准点控制在范围内吗

宝塔的定时任务试固定的

你自己先把需求描述清楚吧

可以基于 cron 表达式+随机时间因子 和锁自己手写一个调度

你要求的就不是一个精确时间,怎么精准控制呢?要么 3 分钟,要么 8 分钟,你得确定执行间隔时间呀

想到了一个办法,不用睡眠等待,手动把定时任务写到 /etc/crontab 文件中,然后在你的脚本最后加上一段替换脚本,执行完脚本去更新这个文件中的间隔时间

短时间执行的可不可以考虑使用 延时队列呢? Redis 或者 MQ

是怕定时推送被检测嘛?

是的 app 抓包的

我最近也在做类似功能,一个比较简单的 selenium 定时回复程序,定时执行总是被系统删除。
windows 下只知道可以用计算机管理里面的基本任务来定时执行脚本,而那个基本任务的触发器必须指定具体时间,很头疼≡(▔﹏▔)≡

想要保证 crontab 单任务的话,可以试试 flock 给要执行的程序加锁。

随机时间放在 php 程序的开头,进入先 sleep 一个随机数,再执行。

简单,定时器执行任务脚本。脚本最后加上如下逻辑:删除定时器,再写入一个新的执行当前脚本的任务,执行时间是 a-b 分钟之后。

python 的 adscheduler 可以指定一个 cron 同时只能有 1 个实例在跑

数据地带为您的网站提供全球顶级IDC资源