Cron工作和随机时间,在给定的时间内

时间:2012-01-28 23:15:17

标签: bash cron sh

我需要能够在完全随机的时间内每天运行20次PHP脚本。我也希望它只在上午9点到晚上11点之间运行。

我熟悉在linux中创建cron作业。

12 个答案:

答案 0 :(得分:115)

是的,是的,这个问题已经过了一年多了,但也许我可以添加一些有用的东西:

如何在上午9点到晚上11点之间每天20次随机偏移?这在cron中有点棘手,因为你将执行时间分为14小时。我不太喜欢其他答案,因为他们需要为你的php脚本编写一个bash包装器脚本。

但是,如果你允许我在上午8:30到晚上11:09之间自由地将时间和频率限制放宽到13次,这可能会解决问题,并且所有这些都在你的crontab范围内:

30 8-21/* * * * sleep ${RANDOM:0:2}m ; /path/to/script.php

$ {RANDOM:3:2}使用其他人上面提到的bash的$ RANDOM,但添加了bash数组切片。由于bash变量是无类型的,伪随机带符号的16位数被截断为其5个十进制数字中的前2位,为您提供简洁的单行程序,用于在10到99分钟之间延迟您的cronjob(尽管分布偏向于10至32)。

以下内容也可能适用于你,但我发现由于某些原因它确实“不那么随机”(也许Benford定律是通过调制伪随机数来触发的。嘿,我不知道,我不及数学...把它归咎于bash!):

30 8-21/* * * * sleep $[RANDOM\%90]m ; /path/to/script.php

你需要将模数渲染为'\%',因为cron(好吧,至少Linux'vixie-cron')在遇到未转义的'%'时会终止该行。

也许你可以通过添加另一行7小时范围来获得剩余的7个脚本执行。或者放宽限制,在凌晨3点到晚上11点之间运行。

答案 1 :(得分:48)

所以我使用以下命令在凌晨1点到3点30分之间运行命令

0 1 * * * perl -le 'sleep rand 9000' && *command goes here*

我一直在照顾我的随机需求。那是9000秒== 150分钟== 2.5小时

答案 2 :(得分:28)

如果我理解你在寻找什么,你需要做一些有点混乱的事情,比如有一个运行bash脚本的cron作业随机化运行时间......就像这样:

的crontab:

0 9 * * * /path/to/bashscript

和/ path / to / bashscript:

#!/bin/bash

maxdelay=$((14*60))  # 14 hours from 9am to 11pm, converted to minutes
for ((i=1; i<=20; i++)); do
    delay=$(($RANDOM%maxdelay)) # pick an independent random delay for each of the 20 runs
    (sleep $((delay*60)); /path/to/phpscript.php) & # background a subshell to wait, then run the php script
done

一些注意事项:这种做法有点浪费资源,因为它会在早上9点触发20个后台进程,每个进程随机等待几分钟(最多14个小时,即晚上11点),然后启动PHP脚本和退出。此外,由于它使用随机分钟数(而不是秒数),因此开始时间并不像它们那样随机。但是$ RANDOM只上升到32,767,并且在上午9点到晚上11点之间有50,400秒,将秒数随机化也会有点复杂。最后,由于开始时间是随机的并且彼此独立,因此可能(但不太可能)将同时启动两个或更多个脚本实例。

答案 3 :(得分:16)

Cron提供RANDOM_DELAY变量。有关详细信息,请参阅crontab(5)

  

RANDOM_DELAY变量允许延迟随机数量的作业启动   具有变量指定上限的分钟。

这在anacron个职位中很常见,但在crontab中也很有用。

如果你有一些运行良好的工作,你可能需要小心 (分钟)粒度和其他粗糙的。

答案 4 :(得分:6)

我的第一个想法是创建一个cron作业,在作业中随机安排20个。 at实用程序(http://unixhelp.ed.ac.uk/CGI/man-cgi?at)用于在指定时间执行命令。

答案 5 :(得分:4)

我最终使用sleep $(( 1$(date +%N) % 60 )) ; dostuffs(与bash&amp; sh兼容)

1前缀是强制NON base 8解释日期+%N(例如00551454)

不要忘记在crontab文件中使用\%转义%

* * * * *  nobody  sleep $(( 1$(date +\%N) \% 60 )) ; dostuffs 

答案 6 :(得分:1)

at -f [file] [timespec]

echo [command] | at [timespec]

at [timespec] ...和交互式规范  比如script的录音。

命令

在运行时,文本在 stdin -f [file]指定的文件中提供。

TIMESPEC

这里是[timespec] grammar。它可以是:

  • 24小时时间为4位数字,例如010023591620
  • now + 10 minutes
  • 2071-05-31 - 5 hours 12 minutes UTC

如果您明确指定时区,则timespec的some versions可能只允许UTC作为可选的时区参数。

实施例

cat script.sh | at now + $(($RANDOM % 10)) hours $(($RANDOM % 60)) minutes

at -f script.sh now + $(($RANDOM % 10)) hours $(($RANDOM % 60)) minutes

试试看......

您可以通过预先挂起的echo测试bash解析并转义|(管道)。

echo cat script.sh \| at now + $(($RANDOM % 10)) hours $(($RANDOM % 60)) minutes

echo at -f script.sh now + $(($RANDOM % 10)) hours $(($RANDOM % 60)) minutes

要查看已安排的作业,请使用atq使用at -c [jobid]和作业内容(环境变量,设置和命令/脚本)。

注意

系统是cron的一部分,交互式提示实际上捕获了shell的整个当前状态,因此您可以在不指定绝对路径的情况下运行命令。

答案 7 :(得分:1)

我意识到这是一个较旧的线程,但是我想添加一个我经常使用的与随机值相关的东西。而不是使用固定范围和有限范围的$ RANDOM变量,我经常使用

在shell中制作任意范围的随机值
dd if=/dev/urandom bs=4 count=1 2>/dev/null | od -N4 -t u4 -A none

例如,您可以这样做

FULLRANDOM=$(dd if=/dev/urandom bs=4 count=1 2>/dev/null | od -N4 -t u4 -A none)

并克服了本主题中讨论的一些限制。

答案 8 :(得分:0)

对于那些用Google搜索道路的人:

如果您使用的是anacron(Ubuntu台式机和笔记本电脑),那么您可以编辑

/etc/anacrontab

并添加

RANDOM_DELAY=XX 

其中XX是您想要延迟基本工作的分钟数。

Anacron就像cron,但它不希望你的计算机全天候运行(就像我们的笔记本电脑一样),并且会因为系统停机而运行它错过的脚本。

答案 9 :(得分:0)

al-x的解决方案对我不起作用,因为crontab命令不是在bash中执行,而是在sh中执行。起作用的是:

30 8 * * * bash -c "sleep $[RANDOM\%90]m" ; /path/to/script.py

答案 10 :(得分:0)

您可以在此示例中尝试在执行命令之前使用随机时间:

#!/bin/bash
# start time
date +"%H:%M:%S"

# sleep for 5 seconds
sleep $(shuf -i 1-25 -n 1)
# end time
date +"%H:%M:%S"

答案 11 :(得分:0)

如何创建每天重写crontab的脚本?

  1. 读取当前的任务(A)
  2. 选择随机时间(B)
  3. 重写以前的任务(A),添加新的随机任务(B)
  4. 确保首先添加到cron中以运行此脚本。