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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/9049460/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-09 21:35:37  来源:igfitidea点击:

Cron jobs and random times, within given hours

bashcronsh

提问by floatleft

I need the ability to run a PHP script 20 times a day at completely random times. I also want it to run only between 9am - 11pm.

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

I'm familiar with creating cron jobs in linux.

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

采纳答案by Gordon Davisson

If I understand what you're looking for, you'll need to do something a bit messy, like having a cron job that runs a bash script that randomizes the run times... Something like this:

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

crontab:

定时任务:

0 9 * * * /path/to/bashscript

and in /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

A few notes: this approach it a little wasteful of resources, as it fires off 20 background processes at 9am, each of which waits around for a random number of minutes (up to 14 hours, i.e. 11pm), then launches the php script and exits. Also, since it uses a random number of minutes (not seconds), the start times aren't quite as random as they could be. But $RANDOM only goes up to 32,767, and there are 50,400 seconds between 9am and 11pm, it'd be a little more complicated to randomize the seconds as well. Finally, since the start times are random and independent of each other, it's possible (but not very likely) that two or more instances of the script will be started simultaneously.

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

回答by al-x

Yeah, yeah, the question is over a year old, but maybe I can add something useful:

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

How to cron something at a random offset 20 times a day between 9am and 11pm? That's kinda tricky within cron, because you are dividing 14 hours by 20 execution times. I don't like the other answers very much because they require writing a bash wrapper script for your php script.

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

However, if you'll allow me the liberty to ease the timing and frequency restriction to 13 times between 8:30am and 11:09pm, this might do the trick, and all within the confines of your crontab:

但是,如果您允许我在上午 8 点 30 分到晚上 11 点 09 分之间将时间和频率限制放宽到 13 次,这可能会奏效,而且所有这些都在您的 crontab 范围内:

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

${RANDOM:3:2} uses bash's $RANDOM that other people have mentioned above, but adds bash array slicing. Since bash variables are untyped, the pseudo-random signed 16-bit number gets truncated to the first 2 of its 5 decimal digits, giving you a succinct one-liner for delaying your cronjob between 10 and 99 minutes (though the distribution is biased towards 10 to 32).

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

The following might also work for you, but I found it do be "less random" for some reason (perhaps Benford's Law is triggered by modulating pseudo-random numbers. Hey, I don't know, I flunked math... Blame it on bash!):

以下内容可能也适用于您,但我发现由于某种原因它确实“不那么随机”(也许本福德定律是通过调制伪随机数触发的。嘿,我不知道,我数学不及格......怪它在 bash 上!):

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

You need to render modulus as '\%' above because cron (well, at least Linux 'vixie-cron') terminates the line when it encounters an unescaped '%'.

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

Maybe you could get the remaining 7 script executions in there by adding another line with another 7-hour range. Or relax your restriction to run between 3am and 11pm.

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

回答by Dave

So I'm using the following to run a command between 1AM and 330AM

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

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

That has been taking care of my random needs for me. That's 9000 seconds == 150 minutes == 2.5 hours

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

回答by Micah Elliott

Cron offers a RANDOM_DELAYvariable. See crontab(5)for details.

Cron 提供了一个RANDOM_DELAY变量。详情请参阅crontab(5)

The RANDOM_DELAY variable allows delaying job startups by random amount of minutes with upper limit specified by the variable.

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

This is seen commonly in anacronjobs, but also can be useful in a crontab.

这在anacron作业中很常见,但在crontab.

You might need to be careful with this if you have some jobs that run at fine (minute) granularity and others that are coarse.

如果您有一些作业以精细(分钟)粒度运行而其他作业则粗粒度运行,则您可能需要小心这一点。

回答by klaus

My first thought would be to create one cron job launching 20 randomly scheduled at jobs. The atutility (http://unixhelp.ed.ac.uk/CGI/man-cgi?at) is used for executing commands at specified time.

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

回答by 131

I ended up using sleep $(( 1$(date +%N) % 60 )) ; dostuffs(compatible with bash & sh)

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

The 1 prefix is to force NON base 8 interpretation of date +%N (e.g. 00551454)

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

Do not forget to escape % using \% in a crontab file

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

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

回答by Wilbert

al-x 's Solution does not work for me since crontab commands are not executed in bash but in sh I guess. What does work is:

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

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

回答by mcint

at -f [file] [timespec]

at -f [file] [timespec]

or

或者

echo [command] | at [timespec]

echo [command] | at [timespec]

or

或者

at [timespec]... and interactive specification like script's recording.

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

Command

命令

At runs the text provide on stdinor in the file specified by -f [file].

在运行时在标准输入或由-f [file].

Timespec

时间规格

Here's the [timespec]grammar. It can be something like:

这是[timespec]语法。它可以是这样的:

  • 24-hour time as 4-digit int, e.g. 0100, 2359, 1620
  • now + 10 minutes
  • 2071-05-31 - 5 hours 12 minutes UTC
  • 24 小时制 4 位整数,例如0100, 2359,1620
  • now + 10 minutes
  • 2071-05-31 - 5 hours 12 minutes UTC

If you're explicitly specifying the timezone, some versionsof the timespec might only allow UTCfor the optional timezone argument.

如果您明确指定时区,则某些版本的 timespec 可能只允许UTC可选的 timezone 参数。

Example

例子

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

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

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

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

Try it out...

试试看...

You can test the bash parsing by pre-pending echoand escaping the |(pipe).

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

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

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

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

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

To see jobs scheduled, use atqand job contents (environment vars, setup, and command/script) with at -c [jobid].

要查看计划作业,使用atq和工作内容(环境瓦尔,设置和命令/脚本)用at -c [jobid]

Note

笔记

The system is part of cron, and the interactive prompt actually captures the whole current state of your shell, so you can run commands without specifying absolute paths.

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

回答by Ganesh Krishnan

For those who googled the way here:

对于那些在这里用谷歌搜索的人:

If you are using anacron(Ubuntu desktop and laptop) then you can edit

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

/etc/anacrontab

and add

并添加

RANDOM_DELAY=XX 

Where XX is the amount of minutes you want to delay the base job.

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

Anacron is like cron but it does not expect your computer to be on 24x7 (like our laptops) and will run the scripts that it missed because the system was down.

Anacron 就像 cron,但它不希望您的计算机 24x7 运行(就像我们的笔记本电脑一样)并且会运行由于系统停机而错过的脚本。

回答by Houssin Boulla

You can try with this example to use random times before execute command:

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

#!/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"