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


当前回答

如果您正在运行带有SystemD的最新Linux操作系统,您可以使用SystemD Timer单元以您希望的任何粒度级别运行脚本(理论上可以精确到纳秒),并且—如果您愿意—比Cron所允许的更灵活的启动规则。不需要睡眠工具

在cron文件中只设置一行代码是不够的,但是如果您需要的不是“每分钟”,那么这样做是非常值得的。

SystemD计时器模型基本上是这样的:计时器是在计时器失效时启动服务单元的单元。

因此,对于想要调度的每个脚本/命令,必须有一个服务单元和一个额外的计时器单元。单个计时器单元可以包括多个计划,因此通常不需要多个计时器和一个服务。

下面是一个简单的例子,每10秒记录一次“Hello World”:

(要创建这些文件,您可以使用sudo tee path-to-file并粘贴文件内容,然后按CTRL+D,或使用您选择的文本编辑器)

/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中,如上所述,用于整个系统范围的设置,或者在~/。Config /systemd/user(用户特定的设置),你需要通过运行systemctl enable——now helloworld来启用定时器(而不是服务)。计时器(——now标志也会立即启动计时器,否则,它只会在下一次引导或用户登录后启动)。

这里使用的[Timer]部分字段如下:

OnBootSec - start the service this many seconds after each boot. OnUnitActiveSec - start the service this many seconds after the last time the service was started. This is what causes the timer to repeat itself and behave like a cron job. AccuracySec - sets the accuracy of the timer. Timers are only as accurate as this field sets, and the default is 1 minute (emulates cron). The main reason to not demand the best accuracy is to improve power consumption - if SystemD can schedule the next run to coincide with other events, it needs to wake the CPU less often. The 1ms in the example above is not ideal - I usually set accuracy to 1 (1 second) in my sub-minute scheduled jobs, but that would mean that if you look at the log showing the "Hello World" messages, you'd see that it is often late by 1 second. If you're OK with that, I suggest setting the accuracy to 1 second or more.

As you may have noticed, this timer doesn't mimic Cron all that well - in the sense that the command doesn't start at the beginning of every wall clock period (i.e. it doesn't start on the 10th second on the clock, then the 20th and so on). Instead is just happens when the timer ellapses. If the system booted at 12:05:37, then the next time the command runs will be at 12:05:47, then at 12:05:57, etc. If you are interested in actual wall clock accuracy, then you may want to replace the OnBootSec and OnUnitActiveSec fields and instead set an OnCalendar rule with the schedule that you want (which as far as I understand can't be faster than 1 second, using the calendar format). The above example can also be written as:

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

最后一点:正如你可能猜到的,helloworld。计时器单元启动helloworld。服务单元,因为它们具有相同的名称(减去单元类型后缀)。这是默认值,但是你可以通过设置[Timer]部分的Unit字段来覆盖它。

更多血腥的细节可以在这里找到:

Arch Linux Wiki关于SystemD定时器的页面,提供了一个很好的主题概述,并提供了示例。 男人systemd.timer 男人systemd.time 男人systemd.service 男人systemd.exec

其他回答

Cron的粒度以分钟为单位,并不是设计为每x秒唤醒一次以运行某项操作。在循环中运行你的重复任务,它应该做你需要的:

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

目前我正在使用下面的方法。工作没有问题。

* * * * * /bin/bash -c ' for i in {1..X}; do YOUR_COMMANDS ; sleep Y ; done '

如果你想每N秒运行一次,那么X = 60/N Y = N。

不需要两个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 '\ "insert_latest \”;睡眠30分钟;cd /srv/last_song/releases/20120308133159 && script/rails runner -e production '\ " Song.insert_latest'\ " "

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

nohup watch -n30 "kill -3 NODE_PID" &

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

nohup ... & 

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

谢谢你的回答。简单来说,我喜欢混合的解决方案,crontab上的控件和脚本上的时间划分。这就是我所做的每20秒运行一个脚本(每分钟3次)。Crontab行:

 * * * * 1-6 ./a/b/checkAgendaScript >> /home/a/b/cronlogs/checkAgenda.log

脚本:

cd /home/a/b/checkAgenda

java -jar checkAgenda.jar
sleep 20
java -jar checkAgenda.jar 
sleep 20
java -jar checkAgenda.jar