给定时间内的 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,但有些手册页缺少相关信息。对于那些只需要每个命令轻松“一些随机性”的人来说,这是一个非常聪明的解决方案。 除了其他地方已经提到的警告外,这只有在你有 GNU date 时才有效(你可能在大多数 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。可以是这样的:

24 小时时间为 4 位整数,例如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 &amp;&amp; some_script.sh 我错过了什么还是最大延迟应该设置为 maxdelay=$((14*60/20)) @jenishSakhiya 20 次运行中的每一次的随机延迟都是绝对的(嗯,从上午 9 点开始),与其他运行无关。也就是说,如果其中一个随机延迟出现在 13 小时,这意味着它将在晚上 10 点(上午 9 点后的 13 小时)运行,而不是在任何其他运行后的 13 小时。

以上是关于给定时间内的 Cron 作业和随机时间的主要内容,如果未能解决你的问题,请参考以下文章

在熊猫中生成给定范围内的随机日期

给定'getrand100()'函数获取特定范围内的随机数

Java - 打印给定范围内的随机 IP 地址

随机数生成器不会使用输入字段中的值生成给定范围内的预期数字[重复]

如何让 github 操作中的工作每天随机运行 1 到 50 次?

获取给定间隔内的随机数-重构代码.com