给定时间内的 Cron 作业和随机时间
Posted
技术标签:
【中文标题】给定时间内的 Cron 作业和随机时间【英文标题】:Cron jobs and random times, within given hours 【发布时间】:2012-02-21 09:30:54 【问题描述】:我需要能够在完全随机的时间每天运行 20 次 php 脚本。我还希望它只在上午 9 点到晚上 11 点之间运行。
我熟悉在 linux 中创建 cron 作业。
【问题讨论】:
这个问题不是很好。最终,您希望在上午 9 点到 11 点之间的时间轴上分配 20 个点。但是最小时差有限制吗?早上 9 点到 10 点 30 分之间什么都不做可以接受吗?在 Klaus 的想法看来,唯一可以接受的方法是:在 09:00 选择您的 20 次,这样您就可以满足您可能遇到的任何限制,然后用“at”安排事情。 【参考方案1】:我意识到这是一个较旧的线程,但我想添加一个我经常使用的与随机值相关的东西。我经常在 shell 中创建任意范围的随机值,而不是使用具有固定和有限范围的 $RANDOM 变量
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)
并克服此线程中讨论的一些限制。
【讨论】:
欢迎来到 SO。好吧,不管旧线程与否,这让我去了~$info dd
,我可以理解|
左侧发生了什么,但无法识别右侧。所以,对于我和其他对随机值生成中的overcoming some restrictions
感兴趣的人,为什么不花点时间解释一下 RHS,并为使用你的方法做出更强有力的宣传。解释的深度使人们对您建议的过程及其好处感到满意。谢谢。
嗯,好的。 od aka“八进制转储”采用文件或标准输入并以人类可读的形式转储二进制数据。我们希望我们的数字显示为无符号十进制(-t u4),并且不希望地址索引(-A none)。 -N4 是多余的,因为我们只占用 4 个字节,但也没有什么坏处。我希望这能解释它......【参考方案2】:
创建一个每天重写 crontab 的脚本怎么样?
-
读取当前 crons (A)
选择随机时间 (B)
重写之前的 crons (A),添加新的随机 crons (B)
确保首先添加到 cron 以运行此脚本。
【讨论】:
不要通过发布 cmets 作为答案来规避信誉系统。但是,您的 comment 看起来确实足以成为 一个答案。我建议删除“我没有代表添加评论,但是”。 我刚刚查看了这个答案,并错过了你最后提出问题的部分(我的工作很草率)。不要在答案中提问。针对您有的问题发布您自己的问题。我把你的半问题变成了可以作为答案的东西。 知道了!谢谢。下次我会更加小心,没有恶意。 我确定您没有恶意,也无需过于小心。您概述了一个可能的解决方案 - 最后偶然发现了一点。不用担心!【参考方案3】:您可以尝试使用此示例在执行命令之前使用随机时间:
#!/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"
【讨论】:
【参考方案4】:al-x 的解决方案对我不起作用,因为 crontab 命令不是在 bash 中执行,而是在 sh 我猜。起作用的是:
30 8 * * * bash -c "sleep $[RANDOM\%90]m" ; /path/to/script.py
【讨论】:
我尝试了所有方法,但它仍然不适合我。您的帖子解释了原因,谢谢!$[ ... ]
是不推荐使用的语法,因为 waaaay 回来了;对于这个千年以来的任何东西,你会更喜欢$((RANDOM\%90))m
,它是与 POSIX 兼容的语法(但当然RANDOM
仍然只是 Bash)。【参考方案5】:
我最终使用了sleep $(( 1$(date +%N) % 60 )) ; dostuffs
(兼容 bash 和 sh)
1 前缀是强制对日期 +%N 进行 NON base 8 解释(例如 00551454)
不要忘记在 crontab 文件中使用 \% 转义 %
* * * * * nobody sleep $(( 1$(date +\%N) \% 60 )) ; dostuffs
【讨论】:
如果有人像我一样想知道: %N 提供了当前的 nanos,但有些手册页缺少相关信息。对于那些只需要每个命令轻松“一些随机性”的人来说,这是一个非常聪明的解决方案。 除了其他地方已经提到的警告外,这只有在你有 GNUdate
时才有效(你可能在大多数 Linux 上这样做,但在 Busybox、标准 MacOS 或其他各种 BSD 派生的平台)。【参考方案6】:
对于那些在这里用谷歌搜索的人:
如果您使用的是 anacron(Ubuntu 台式机和笔记本电脑),那么您可以编辑
/etc/anacrontab
并添加
RANDOM_DELAY=XX
其中 XX 是您希望延迟基本作业的分钟数。
Anacron 与 cron 类似,但它不希望您的计算机 24x7 全天候运行(就像我们的笔记本电脑一样),并且会运行由于系统关闭而错过的脚本。
【讨论】:
【参考方案7】:at -f [file] [timespec]
或
echo [command] | at [timespec]
或
at [timespec]
... 和交互规范
喜欢script
的录音。
命令
在运行时,文本在 stdin 或-f [file]
指定的文件中提供。
时间规格
这是[timespec]
grammar。可以是这样的:
0100
, 2359
, 1620
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 的整个当前状态,因此您可以在不指定绝对路径的情况下运行命令。
【讨论】:
【参考方案8】:Cron 提供了一个 RANDOM_DELAY
变量。详情请见crontab(5)
。
RANDOM_DELAY 变量允许将作业启动延迟随机数量 分钟,上限由变量指定。
这在anacron
工作中很常见,但在crontab
中也很有用。
如果您有一些运行良好的作业,您可能需要小心这一点 (分钟)粒度和其他粗粒度。
【讨论】:
我很想使用 RANDOM_DELAY 变量,但在 Ubuntu 14.04.4 LTS 上的 crontab(5) 手册页中找不到任何提示。 这很不幸。我想知道那里是否不支持。我看到它记录在 Centos 7 和 Arch Linux 的联机帮助页中。 这似乎是正确的答案,但你能举个例子吗? 请注意RANDOM_DELAY
只建立一次,并在守护进程的整个运行时保持不变。
RANDOM_DELAY
标志是 cronie-crond 的功能,而 Ubuntu 似乎正在运行缺少此标志的 vixie-cron
。【参考方案9】:
所以我使用以下命令在凌晨 1 点到 330 点之间运行命令
0 1 * * * perl -le 'sleep rand 9000' && *command goes here*
这一直在照顾我对我的随机需求。那是 9000 秒 == 150 分钟 == 2.5 小时
【讨论】:
::MindBLOWN:: 另一个使用一点 perl 的不起眼的地方。 这绝对是最干净的答案 这有点低效,因为你要创建很多进程。【参考方案10】:是的,是的,这个问题已经有一年多了,但也许我可以添加一些有用的东西:
如何在每天上午 9 点到晚上 11 点之间以 20 次随机偏移量 cron 某项内容?这在 cron 中有点棘手,因为您将 14 小时除以 20 执行时间。我不太喜欢其他答案,因为它们需要为您的 php 脚本编写一个 bash 包装脚本。
但是,如果您允许我在上午 8:30 到晚上 11:09 之间将时间和频率限制放宽到 13 次,这可能会奏效,并且所有这些都在您的 crontab 范围内:
30 8-21/* * * * sleep $RANDOM:0:2m ; /path/to/script.php
$RANDOM:3:2 使用了上面其他人提到的 bash 的 $RANDOM,但是添加了 bash 数组切片。由于 bash 变量是无类型的,伪随机有符号 16 位数字被截断为其 5 个十进制数字的前 2 个,为您提供一个简洁的单行代码,用于将您的 cronjob 延迟 10 到 99 分钟(尽管分布偏向于10 到 32)。
以下内容也可能对您有用,但由于某种原因,我发现它确实“不那么随机”(也许本福德定律是通过调制伪随机数触发的。嘿,我不知道,我数学不及格...... . 归咎于 bash!):
30 8-21/* * * * sleep $[RANDOM\%90]m ; /path/to/script.php
您需要将模数呈现为上面的 '\%',因为 cron(至少 Linux 'vixie-cron')在遇到未转义的 '%' 时会终止该行。
也许您可以通过添加另一个 7 小时范围的另一行来获得剩余的 7 个脚本执行。或者放宽在凌晨 3 点到晚上 11 点之间跑步的限制。
【讨论】:
我喜欢迟到的答案。但是如果你想生成一个均匀分布在 10 到 99 范围内的随机整数,而 RANDOM 的输出是 0 到 32,767,那你为什么不直接做$[(RANDOM/368)+10]
呢?
@jsdalton:模运算符不是更好吗? $((RANDOM % 90 + 10))
测试:for i in 0..9999; do echo $((RANDOM % 90 + 10)); done | sort | uniq -c
在许多系统上,cron 默认情况下不使用 bash,因此最好避免使用 bashism $RANDOM
: sleep $(( $(od -N1 -tuC -An /dev/urandom) \% 90 ))m
。
在使用$RANDOM
之前确保crontab
使用bash
。如果你有vixie-cron
(在Ubuntu上似乎是我的情况),那么您可以将SHELL=/bin/bash
添加到顶部。这里还有其他 cron 版本的替代方案:superuser.com/a/264541/260350
当我使用上面的第一个建议时,我得到crontab: errors in crontab file, can't install. Do you want to retry the same edit?
please help【参考方案11】:
我的第一个想法是创建一个 cron 作业,启动 20 个随机安排的作业。 at
实用程序 (http://unixhelp.ed.ac.uk/CGI/man-cgi?at) 用于在指定时间执行命令。
【讨论】:
这里有一个使用 at 的例子:***.com/a/6136145/803174【参考方案12】:如果我明白你在寻找什么,你需要做一些有点混乱的事情,比如让一个 cron 作业运行一个随机化运行时间的 bash 脚本......这样的事情:
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 秒,随机化秒数也会稍微复杂一些。最后,由于开始时间是随机的并且彼此独立,因此有可能(但不太可能)脚本的两个或多个实例同时启动。
【讨论】:
您可以通过删除美元符号并将双括号向左移动(例如((maxdelay = 14 * 60))
或((delay = $RANDOM % maxdelay))
)来使算术分配更具可读性。 sleep
参数仍然需要是您拥有它的方式(尽管您可以添加空格,如果需要)。
这对我也有用。我的自定义 bash 脚本如下所示sleep $[ ( $RANDOM % 60 ) + 1 ]s && some_script.sh
我错过了什么还是最大延迟应该设置为 maxdelay=$((14*60/20))
@jenishSakhiya 20 次运行中的每一次的随机延迟都是绝对的(嗯,从上午 9 点开始),与其他运行无关。也就是说,如果其中一个随机延迟出现在 13 小时,这意味着它将在晚上 10 点(上午 9 点后的 13 小时)运行,而不是在任何其他运行后的 13 小时。以上是关于给定时间内的 Cron 作业和随机时间的主要内容,如果未能解决你的问题,请参考以下文章
随机数生成器不会使用输入字段中的值生成给定范围内的预期数字[重复]