我有一个cron需要每30秒运行一次。

以下是我所拥有的:

*/30 * * * * /bin/bash -l -c 'cd /srv/last_song/releases/20120308133159 && script/rails runner -e production '\''Song.insert_latest'\'''

它能运行,但它是每30分钟或30秒运行一次吗?

此外,我一直在阅读,如果我经常运行cron,它可能不是最好的工具。有没有其他更好的工具,我可以使用或安装在Ubuntu 11.04上,这将是一个更好的选择?有没有办法修复上面的cron?


当前回答

你不能。Cron的粒度为60秒。

* * * * * cd /srv/last_song/releases/20120308133159 && script/rails runner -e production '\''Song.insert_latest'\''
* * * * * sleep 30 && cd /srv/last_song/releases/20120308133159 && script/rails runner -e production '\''Song.insert_latest'\''

其他回答

在分钟指示符中有*/30 -这意味着每分钟,但步长为30(换句话说,每半小时)。由于cron不能精确到几分钟的分辨率,您需要找到另一种方法。

有一种可能,虽然有点拼凑(a),是有两个工作,一个抵消30秒:

# Need these to run on 30-sec boundaries, keep commands in sync.
* * * * *              /path/to/executable param1 param2
* * * * * ( sleep 30 ; /path/to/executable param1 param2 )

您将看到我添加了注释并进行了格式化,以确保它们易于保持同步。

这两个cron作业实际上每分钟运行一次,但后者在执行作业的“肉”/path/to/executable之前会等待半分钟。

关于其他(非基于cron的)选项,请参阅这里的其他答案,特别是提到fcron和systemd的答案。假设你的系统有能力使用它们(比如安装fcron或者有一个带有systemd的发行版),这些可能是更可取的。


如果您不想使用这个笨拙的解决方案,您可以使用一个基于循环的解决方案,并进行了一个小的修改。你仍然需要管理保持你的进程以某种形式运行,但是,一旦排序,下面的脚本应该工作:

#!/bin/env bash

# Debug code to start on minute boundary and to
# gradually increase maximum payload duration to
# see what happens when the payload exceeds 30 seconds.

((maxtime = 20))
while [[ "$(date +%S)" != "00" ]]; do true; done

while true; do
    # Start a background timer BEFORE the payload runs.

    sleep 30 &

    # Execute the payload, some random duration up to the limit.
    # Extra blank line if excess payload.

    ((delay = RANDOM % maxtime + 1))
    ((maxtime += 1))
    echo "$(date) Sleeping for ${delay} seconds (max ${maxtime})."
    [[ ${delay} -gt 30 ]] && echo
    sleep ${delay}

    # Wait for timer to finish before next cycle.

    wait
done

诀窍是使用sleep 30,但在有效负载运行之前在后台启动它。然后,在有效负载完成后,只需等待背景睡眠完成。

如果有效载荷需要n秒(其中n <= 30),那么有效载荷之后的等待时间将是30 - n秒。如果它需要超过30秒,那么下一个循环将被延迟,直到有效载荷完成,但不会更长。

您将看到其中的调试代码以一分钟为边界开始,以使输出最初更容易遵循。我还逐渐增加最大有效负载时间,因此您最终会看到有效负载超过30秒的周期时间(输出额外的空行,因此效果很明显)。

下面是一个示例运行(其中周期通常在前一个周期后30秒开始):

Tue May 26 20:56:00 AWST 2020 Sleeping for 9 seconds (max 21).
Tue May 26 20:56:30 AWST 2020 Sleeping for 19 seconds (max 22).
Tue May 26 20:57:00 AWST 2020 Sleeping for 9 seconds (max 23).
Tue May 26 20:57:30 AWST 2020 Sleeping for 7 seconds (max 24).
Tue May 26 20:58:00 AWST 2020 Sleeping for 2 seconds (max 25).
Tue May 26 20:58:30 AWST 2020 Sleeping for 8 seconds (max 26).
Tue May 26 20:59:00 AWST 2020 Sleeping for 20 seconds (max 27).
Tue May 26 20:59:30 AWST 2020 Sleeping for 25 seconds (max 28).
Tue May 26 21:00:00 AWST 2020 Sleeping for 5 seconds (max 29).
Tue May 26 21:00:30 AWST 2020 Sleeping for 6 seconds (max 30).
Tue May 26 21:01:00 AWST 2020 Sleeping for 27 seconds (max 31).
Tue May 26 21:01:30 AWST 2020 Sleeping for 25 seconds (max 32).
Tue May 26 21:02:00 AWST 2020 Sleeping for 15 seconds (max 33).
Tue May 26 21:02:30 AWST 2020 Sleeping for 10 seconds (max 34).
Tue May 26 21:03:00 AWST 2020 Sleeping for 5 seconds (max 35).
Tue May 26 21:03:30 AWST 2020 Sleeping for 35 seconds (max 36).

Tue May 26 21:04:05 AWST 2020 Sleeping for 2 seconds (max 37).
Tue May 26 21:04:35 AWST 2020 Sleeping for 20 seconds (max 38).
Tue May 26 21:05:05 AWST 2020 Sleeping for 22 seconds (max 39).
Tue May 26 21:05:35 AWST 2020 Sleeping for 18 seconds (max 40).
Tue May 26 21:06:05 AWST 2020 Sleeping for 33 seconds (max 41).

Tue May 26 21:06:38 AWST 2020 Sleeping for 31 seconds (max 42).

Tue May 26 21:07:09 AWST 2020 Sleeping for 6 seconds (max 43).

如果您想避免这种笨拙的解决方案,这可能更好。您仍然需要一个cron作业(或等效作业)来定期检测该脚本是否正在运行,如果没有,则启动它。但是脚本本身会处理计时。


(a)我的一些同事会说拼板是我的专长:-)

Have a look at frequent-cron - it's old but very stable and you can step down to micro-seconds. At this point in time, the only thing that I would say against it is that I'm still trying to work out how to install it outside of init.d but as a native systemd service, but certainly up to Ubuntu 18 it's running just fine still using init.d (distance may vary on latter versions). It has the added advantage (?) of ensuring that it won't spawn another instance of the PHP script unless a prior one has completed, which reduces potential memory leakage issues.

编写一个shell脚本 创建.sh文件

纳米every30second.sh

并编写脚本

#!/bin/bash
For  (( i=1; i <= 2; i++ ))
do
    write Command here
    sleep 30
done

然后为该脚本设置cron crontab - e

(*****/家庭/用户名/每30秒.sh)

这个cron调用.sh文件每1分钟&在.sh文件命令在1分钟内运行2次

如果你想运行脚本5秒,那么将30替换为5,并像这样更改for循环:I <= 12;我+ +))

当你选择任意一秒时,计算60/你的秒并写入for循环

你可以看看我对这个类似问题的回答

基本上,我在这里包含了一个名为“runEvery.sh”的bash脚本,您可以用cron每1分钟运行一次该脚本,并将希望运行的实际命令和希望运行该命令的频率(以秒为单位)作为参数传递。

就像这样

* * * * ~/bin/ runeveryes.sh 5 myScript.sh

我刚刚有一个类似的任务要做,并使用了以下方法:

nohup watch -n30 "kill -3 NODE_PID" &

我需要在几个小时内每30秒执行一次定期kill -3(以获得程序的堆栈跟踪)。

nohup ... & 

这是在这里确保我不会失去手表的执行,如果我松散的外壳(网络问题,windows崩溃等…)