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

评论

CommaToast,如果您的Javascript或Java应用由于某种原因而失败并退出,该怎么办?如何重启? :-)

添加一个小的NodeJS应用,大声笑。为什么不使用一点c ++应用程序?在使用它时,我们可以将其命名为“ cron”并将其作为服务运行。

可能重复如何每分钟运行一次Cron Jobs?
我只是在查看用户个人资料时发现此问题的,并且发现您不到1小时前就上网了(只是检查acc是否仍在使用中),是否有任何特定原因导致您不接受以下任何答案? />

#1 楼

分钟说明符中有*/30-表示每分钟,但以30为步长(换句话说,每半小时)。由于cron不会降低到亚分钟分辨率,因此您将需要寻找另一种方法。
一种可能性(虽然有点麻烦)可能有两项工作,其中一项要抵消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的)选项,请执行此处的其他答案,尤其是提到cronfcron的答案。如果您的系统有能力使用它们(例如安装systemd或安装了带有fcron的发行版),则可能更可取。

如果您不想使用kludgy解决方案,则可以使用基于循环的解决方案,并进行少量修改。您仍然需要设法使进程以某种形式运行,但是,排序之后,以下脚本应该可以工作:
#!/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

诀窍是使用systemd,但要在后台启动它您的有效载荷运行。然后,在完成有效负载后,只需等待后台sleep 30完成。
如果有效负载需要sleep秒(其中n),则在有效负载之后的等待时间将是n <= 30秒。如果要花费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).

如果要避免麻烦的解决方案,这可能会更好。您仍然需要一个30 - n作业(或同等作业)来定期检测此脚本是否正在运行,如果没有运行,请启动它。但是脚本本身然后处理时间。

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

评论


这是一个很好的解决方法,以至于我认为它超越了它的模糊性

–问号
15年1月12日在10:25

@ rubo77,仅当运行时间少于一秒时:-)如果花费了29秒,它将发生在0:00:00、0:00.59、0:01:00、0:01:59等。

– paxdiablo
2015年4月23日在5:30



超级偷偷摸摸,很有创意!

–拉斐尔(K Raphael)
16年8月22日在19:47

第二行的圆括号是什么?

–奈杰尔·奥尔德顿(Nigel Alderton)
18/09/5在12:55

这是一个很好的解决方案,对于某些需要在几分钟之内执行的任务,否则会严重影响其有效性。谢谢。

–Fiddy Bux
19年1月9日,0:18

#2 楼

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


评论


这种语法是否等同于paxdiablo的语法?还是有细微的差异?

–尼古拉斯·拉乌尔(Nicolas Raoul)
18 Mar 26 '18在8:55

区别在于:我使用了二进制文件的原始路径。 @paxdiablo使用了一种元语法。 (并调用一个子shell)

–wildplasser
18 Mar 26 '18在22:15

我的意思是使用&&代替(;)。

–尼古拉斯·拉乌尔(Nicolas Raoul)
18-3-27的6:16

抱歉。不,有区别; &&运算符会短路,因此如果前一个失败,则不会执行链中的下一个命令。

–wildplasser
18 Mar 27 '18在7:49

对于亚分钟分辨率,此粒度不应成为问题。

– Juan Isaza
19年7月18日在16:15

#3 楼

如果您正在运行带有SystemD的最新Linux操作系统,则可以使用SystemD Timer单元以所需的任意粒度级别(理论上可以低至纳秒)运行脚本,并且-如果您愿意-可以比Cron允许的启动规则更灵活。不需要sleep繁琐的操作

在cron文件中进行设置要比在一行中花费更多,但是如果您需要的内容比“每分钟”还多,那么这是值得的。 />
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


设置这些单元后(in如上所述,对于系统范围的设置为/etc/systemd/system,对于用户特定的设置,为~/.config/systemd/user,您需要通过运行systemctl enable --now helloworld.timer--now标志也立即启动计时器)来启用计时器(尽管不是服务) ,它将仅在下一次启动或用户登录后启动。)

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




OnBootSec -每次启动后数秒内启动服务。

OnUnitActiveSec-上次启动服务后数秒内启动服务。这就是导致计时器重复执行并表现为定时作业的原因。
AccuracySec-设置计时器的精度。计时器的准确性仅与该字段设置的一样,并且默认值为1分钟(模拟cron)。不要求最佳精度的主要原因是为了降低功耗-如果SystemD可以安排下一次运行与其他事件同时发生,则它需要较少地唤醒CPU。上例中的1ms并不理想-我通常在次分钟的计划工作中将精度设置为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部分设置Unit字段来覆盖它。

更多详细信息请参见:



/>关于SystemD计时器的Arch Linux Wiki页面,通过示例很好地概述了本主题。
[Timer]
man systemd.timer
man systemd.time
man systemd.service


评论


我经常在评论部分找到这样的更好答案。恕我直言,尽管cron已排定在预定的工作中使用,但此答案应为公认的答案,因为它不是“黑客”工作,并且考虑到所需的时间间隔/频率,可能会并行执行长时间运行的任务

–旗袍
19年5月18日在4:18

极好的答案,应该是选定的答案

–GuidedHacking
20-2-21在16:42

我想知道在Alpine上是否可行,因为人们说那里是OpenRC,而不是系统化的。

– Nakilon
20-10-29在8:30

@Nakilon:Alpine最初是用于容器的简约操作系统,因此它不需要复杂的系统运行时,例如SystemD。 IMO OpenRC完全是容器的一个过大杀伤力-如果您有充分的理由使用多进程容器,请使用有监督能力的容器或诸如此类的简单容器,并且我也质疑您在这种情况下需要运行cron的问题。我知道有些人在非容器情况下运行Alpine,并且希望他们停止使用-Alpine甚至没有通过作为主要操作系统运行所需的非常基本的强化和质量检查。

–古斯
20-10-29在10:32



@Guss,目标不是关于多进程,而是要比在一分钟内更频繁地运行任务。我需要它在10秒内运行一次。我目前正在使用cron调用.sh脚本,它带有六个像这样的链式命令{ruby main.rb&sleep 10;} && ... && ruby​​main.rb。您会看到,在上一次迭代中,我不称睡眠-我认为我需要像这样内联循环,因为我遇到了“进程仍在运行”错误。错误消息不见了,但它仍然跳过第二次迭代,我不这样做。仍在调试中。

– Nakilon
20-10-29在11:01

#4 楼

Cron的粒度以分钟为单位,并非旨在每隔x秒唤醒一次以运行某些内容。在循环中运行重复的任务,它应该可以满足您的需求:

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


评论


请记住,这并不完全相同。例如,如果作业花费25秒,它将每55秒而不是每30秒开始。可能并不重要,但是您应该意识到可能的后果。

– paxdiablo
2012年8月8日14:52



您可以在后台运行该作业,然后它将在几乎30秒内运行。

–克里斯·科斯顿(Chris Koston)
13年3月22日在15:50

而[true]睡觉30#做您需要做的事情---------做的应该是小写

–寺庙
13年11月28日在21:02



虽然[true]会不会因为cron每分钟启动一个新实例而使您拥有相同脚本的许多实例?

– Carcamano
2014年1月23日15:09

您可以在$ remainingTime处进行睡眠,其中remainingTime为30减去工作所花费的时间(如果花费> 30秒,则将其限制为零)。因此,您需要花费在实际工作之前和之后的时间,并计算出差异。

– mahemoff
2014-09-15 10:29



#5 楼

不需要两个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'\''"

评论


注意:仅当脚本运行时间少于一秒钟时,此命令才能正确运行

–rubo77
2015年4月23日下午5:48

Rubo-如果作业需要花费数秒(而不是毫秒或微秒)的时间来完成,那么您不会每三十秒运行一次就可以每分钟运行两次。所以是的,从30开始,然后从中减去每次运行的大概秒数(如果大于1秒)。

–安德鲁(Andrew)
15年4月30日在15:51

如果您想分别接收每次运行的错误报告,这也无济于事。

– joeln
19年7月3日在1:43

joelin-我提供的命令不会阻止获取日志或输出数据,我简化了该命令以解决该问题。为了捕获日志记录,如果需要日志记录,每个命令可以/应该重定向输出,例如,脚本/ railsrunner -e生产'\'Song.insert_latest'\'可以写为脚本/ railsRunner -e生产'\' 'Song.insert_latest'\''2>&1> / path_to_logfile,并且可以对单个cron条目中的每个命令再次执行。

–安德鲁(Andrew)
19年9月8日15:52

#6 楼

Cron作业不能用于以秒为间隔计划作业。也就是说,您无法安排cron作业每5秒运行一次。另一种方法是编写一个在其中使用sleep 5命令的shell脚本。

每隔5秒创建一个shell脚本。使用bash while循环创建一个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 &


评论


时间会漂移。例如,如果backup.sh需要1.5秒才能运行,它将每6.5秒执行一次。有一些方法可以避免这种情况,例如sleep $((5-$(date +%s)%5))

–基思·汤普森(Keith Thompson)
14-10-15在6:37

我是nohup的新手,在执行您的示例时,nohup返回“无此类文件或目录”。经过一些搜索,您似乎在nohup之后错过了“ sh”。像这样:$ nohup sh ./every-5-seconds.sh&

– VHanded
15年10月23日在5:40

#7 楼

您可以查看我对类似问题的回答

基本上,我已经在其中包含了一个名为“ runEvery.sh”的bash脚本,您可以每隔1分钟使用cron运行一次,并将真实命令作为参数传递您想要运行的频率以及运行频率(以秒为单位)。

类似的东西

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

#8 楼

使用手表:

$ watch --interval .30 script_to_run_every_30_sec.sh


评论


我可以使用$ watch --interval .10 php some_file.php之类的东西吗?或观看仅适用于.sh文件?

– Yevhenii Shashkov
17-6-23在10:38



您可以通过手表运行任何东西。但是,间隔是在下一条命令的开始与结束之间,因此--interval .30不会每分钟运行两次。即观看-n 2“ sleep 1 && date +%s”,它将每3s增加一次。

– jmartori
19年6月20日在21:37

请注意,手表是为终端使用而设计的,因此-尽管它可以在没有终端的情况下工作(先运行nohup然后注销),或者在伪造的终端(例如屏幕)下运行,但手表却无法提供类似cron的行为,例如恢复从失败,启动后重新启动,等等。

–古斯
19-11-29在11:32



#9 楼

目前,我正在使用以下方法。
* * * * * /bin/bash -c ' for i in {1..X}; do YOUR_COMMANDS ; sleep Y ; done '

如果您想每隔N秒运行一次,则X将为60 / N,Y将为N。

评论


您可能希望将YOUR_COMMANDS更改为YOUR_COMMANDS&,以便将命令启动到后台,否则,如果该命令花费了不到一秒钟的时间-它将延迟下次启动。因此,对于X = 2和Y = 30,如果该命令花费10秒-它会在几分钟后启动,然后在40秒后启动,而不是30秒。Kudus到@paxdiablo。

–古斯
19-10-12在7:06

出于某种原因,如果我省略了/ bin / bash -c部分(包括参数引号),则脚本仅每分钟运行一次,而忽略了迭代(在我的情况下,X = 12和Y = 5)。

– abiyi
19-10-27在21:48



我得到进程已经在运行。可能是因为睡眠需要几毫秒的时间才能死掉。最好不要叫上一次睡眠,例如,在1分钟内仅将其叫5次,停顿10秒。

– Nakilon
20-10-29在9:57

#10 楼

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

评论


PHP开发人员的自白; )

–埃里克·基加西(Eric Kigathi)
17年2月24日在17:04

实际上,是一名系统工程师的自白使PHP开发人员能够.... :)

– Adi Chiru
17年11月11日17:35

#11 楼

在目录/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

#12 楼

Crontab作业可用于以分钟/小时/天,而不是以秒为单位计划作业。替代方法:

创建一个脚本,每30秒执行一次:

#!/bin/bash
# 30sec.sh

for COUNT in `seq 29` ; do
  cp /application/tmp/* /home/test
  sleep 30
done


使用crontab -e和crontab执行该脚本:

* * * * * /home/test/30sec.sh > /dev/null


评论


如果我理解正确,则此脚本将运行30次,并在每次迭代之间等待30秒。在cron中每分钟运行一次有什么意义?

–FuzzyAmi
17/12/26在10:37



#13 楼

编写一个Shell脚本
每30秒创建一个.sh文件
nano。sh
并编写脚本
#!/bin/bash
For  (( i=1; i <= 2; i++ ))
do
    write Command here
    sleep 30
done

然后为该脚本设置cron
crontab -e
(* * * * * /home/username/every30second.sh)
此cron调用.sh文件每1分钟运行一次,并且.sh文件命令在1分钟内运行2次
如果要运行脚本5秒钟,则将30替换为5,然后像这样更改for循环:For (( i=1; i <= 12; i++ ))
,当您选择任何秒数时,请计算60 /您的秒数,然后写入For循环

#14 楼

您可以将该脚本作为服务运行,每30秒重新启动一次

注册服务

sudo vim /etc/systemd/system/YOUR_SERVICE_NAME.service


在下面的命令中粘贴

Description=GIVE_YOUR_SERVICE_A_DESCRIPTION

Wants=network.target
After=syslog.target network-online.target

[Service]
Type=simple
ExecStart=YOUR_COMMAND_HERE
Restart=always
RestartSec=10
KillMode=process

[Install]
WantedBy=multi-user.target


重新加载服务

sudo systemctl daemon-reload


启用服务

sudo systemctl enable YOUR_SERVICE_NAME


/>启动服务

sudo systemctl start YOUR_SERVICE_NAME


检查服务状态

systemctl status YOUR_SERVICE_NAME


#15 楼

感谢所有的好的答案。为简单起见,我喜欢使用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 


评论


1-6代表什么?

–Phantom007
19年8月15日在6:14

@ Phantom007 1-6表示星期一至星期六,其中“-”是范围,“ 0”是星期日。这是一个很好的链接,很好地解释了所有字段以及可以在哪里进行测试的地方:“ crontab.guru /#* _ * _ * _ * _ 1-6”

– jfajunior
19年8月20日14:35



#16 楼

我只是要做类似的任务,并使用以下方法:

nohup watch -n30 "kill -3 NODE_PID" &


我需要定期执行kill -3(以获取程序的堆栈跟踪信息)每30秒持续几个小时。

nohup ... & 


这是为了确保如果我松开外壳(网络问题,Windows等),我也不会失去手表的执行力崩溃等...)

#17 楼

看看频繁的cron-它很老但是很稳定,您可以降低到微秒级。在这一点上,我唯一要反对的是,我仍在尝试如何在init.d之外安装它,但作为本机systemd服务,但是直到Ubuntu 18为止,它只能运行仍然可以使用init.d进行操作(距离在以后的版本中可能会有所不同)。它具有附加的优势(?),确保除非之前的脚本实例已完成,否则它不会生成该PHP脚本的另一个实例,从而减少了潜在的内存泄漏问题。

#18 楼

在shell循环中运行,例如:

#!/bin/sh    
counter=1
while true ; do
 echo $counter
 counter=$((counter+1))
 if [[ "$counter" -eq 60 ]]; then
  counter=0
 fi
 wget -q http://localhost/tool/heartbeat/ -O - > /dev/null 2>&1 &
 sleep 1
done


评论


即使假设60应该是30,您也可能希望将该wget移至if语句中,否则它每秒执行一次。无论如何,我不确定这是否比单次睡眠30更好。如果您正在监视UNIX的实际时间而不是计数器,那将有所作为。

– paxdiablo
18年7月13日在1:54

回显计数器打印出来的内容,如果不在后台运行wget,则可以找出由于执行命令而延迟的时间。

–Lo Vega
18年7月18日在2:03

#19 楼

为什么不只添加2个连续的命令条目,它们都从不同的秒开始?
0 * * * * /bin/bash -l -c 'cd /srv/last_song/releases/20120308133159 && script/rails runner -e production '\''Song.insert_latest'\'''
30 * * * * /bin/bash -l -c 'cd /srv/last_song/releases/20120308133159 && script/rails runner -e production '\''Song.insert_latest'\'''