当前位置: 首页>>技术问答>>正文


每30秒运行一次cron

, ,

问题描述

好的,我有一个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?

最佳解决思路

您在分钟说明符中有*/30 – 这意味着每分钟但步长为30(换句话说,每半小时)。由于cron没有达到sub-minute分辨率,您需要找到另一种方法。

一种可能性,虽然它有点像kludge,但是有两个工作,一个偏移30秒:

* * * * * /path/to/executable param1 param2
* * * * * ( sleep 30 ; /path/to/executable param1 param2 )

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

次佳解决思路

你不能。 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'\''

第三种解决思路

Cron的粒度是几分钟,并不是为了唤醒每个x秒来运行某些东西。在循环中运行重复任务,它应该做你需要的:

#!/bin/env bash
while [ true ]; do
 sleep 30
 # do what you need to here
done

第四种思路

不需要两个cron条目,你可以把它放在一个:

* * * * * /bin/bash -l -c "/path/to/executable; sleep 30 ; /path/to/executable"

所以在你的情况下:

* * * * * /bin/bash -l -c "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'\''"

第五种思路

你可以看看我对this similar question的回答

基本上,我已经在其中包含了一个名为”runEvery.sh”的bash脚本,您可以每隔1分钟使用cron运行该脚本,并将您希望运行的实际命令和您想要运行它的频率作为参数传递。

这样的事情

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

第六种思路

Cron作业不能用于在几秒钟内安排作业。即你不能安排一个cron作业每5秒运行一次。另一种方法是编写一个使用sleep 5命令的shell脚本。

使用bash while循环创建一个shell脚本every-5-seconds.sh,如下所示。

$ cat every-5-seconds.sh
#!/bin/bash
while true
do
 /home/ramesh/backup.sh
 sleep 5
done

现在,使用nohup在后台执行此shell脚本,如下所示。即使您从会话中注销,这也将继续执行脚本。这将每5秒执行一次backup.sh shell脚本。

$ nohup ./every-5-seconds.sh &

第七种思路

使用 watch :

$ watch --interval .30 script_to_run_every_30_sec.sh

第八种思路

在目录/etc/cron.d/

新建一个文件excute_per_30s

* * * * * yourusername  /bin/date >> /home/yourusername/temp/date.txt
* * * * * yourusername sleep 30; /bin/date >> /home/yourusername/temp/date.txt

将每30秒运行一次cron

第九种思路

使用fcron(http://fcron.free.fr/) – 以秒为单位提供粒度,比cron(vixie-cron)更好,功能更丰富,也更稳定。我曾经制作过愚蠢的事情,例如在一台机器上运行非常愚蠢的设置运行大约60个PHP脚本,它仍然可以完成它的工作!

第十种思路

如果您使用SystemD运行最近的Linux操作系统,您可以使用SystemD Timer单元以您希望的任何粒度级别(理论上低至纳秒)运行您的脚本,并且 – 如果您愿意 – 比Cron允许的更灵活的启动规则。无需sleep kludges

设置比cron文件中的单行要多一些,但如果你需要比”Every minute”更好的东西,那么值得努力。

SystemD计时器模型基本上是这样的 – 计时器是在计时器过去时启动服务单元的单位。

因此,对于要安排的每个脚本/命令,您必须具有服务单元,然后是其他计时器单元。单个计时器单元可以包含多个计划,因此您通常不需要多个计时器和一个服务。

这是一个每10秒记录”Hello World”的简单示例:

/etc/systemd/system/helloworld.service

[Unit]
Description=Say Hello
[Service]
ExecStart=/usr/bin/logger -i Hello World

/etc/systemd/system/helloworld.timer

[Unit]
Description=Say Hello every 10 seconds
[Timer]
OnBootSec=10
OnUnitActiveSec=10
AccuracySec=1ms
[Install]
WantedBy=timers.target

设置这些单元后(在/etc /systemd /system中,如上所述,对于system-wide设置,或在〜/.config /systemd /user用于user-specific设置),您需要启用计时器(不是服务虽然)通过运行systemctl enable helloworld.timer。如果要立即启动计时器(而不是在重新启动后等待它启动),还要运行systemctl start helloworld.timer。

此处使用的[Timer]部分字段如下:

  • OnBootSec – 每次启动后几秒钟启动服务。

  • OnUnitActiveSec – 在上次启动服务后的几秒钟内启动服务。这就是导致计时器重复并且表现得像cron作业的原因。

  • AccuracySec – 设置计时器的准确性。定时器仅与此字段集一样准确,默认值为1分钟(模拟cron)。不要求最佳精度的主要原因是提高功耗 – 如果SystemD可以安排下一次运行与其他事件一致,则需要更少地唤醒CPU。上例中的1ms并不理想 – 我通常在sub-minute预定作业中将精度设置为1(1秒),但这意味着如果查看显示”Hello World”消息的日志,您会发现它经常出现迟了1秒。如果您对此感到满意,我建议将精度设置为1秒或更长。

正如您可能已经注意到的那样,这个计时器并不能很好地模仿Cron – 从命令不会在每个挂钟时段开始时开始(即它不会在时钟的第10秒开始,那么20日等等)。相反,只是在计时器瘫痪时发生。如果系统在12:05:37启动,则下次命令运行时间为12:05:47,然后是12:05:57等。如果您对实际挂钟准确度感兴趣,那么您可以想要替换OnBootSecOnUnitActiveSec字段,而是使用您想要的计划设置OnCalendar规则(根据我的理解,使用日历格式不能超过1秒)。上面的例子也可以写成:

OnCalendar=*-*-* *:*:00,10,20,30,40,50

最后注意:正如您可能猜到的那样,helloworld.timer单元启动helloworld.service单元,因为它们具有相同的名称(减去单元类型后缀)。这是默认设置,但您可以通过为[Timer]部分设置Unit字段来覆盖它。

更多血腥细节可在以下网址找到:

参考资料

本文由Ubuntu问答整理, 博文地址: https://ubuntuqa.com/article/6250.html,未经允许,请勿转载。