我可以比每分钟更频繁地执行Cron工作吗?


44

是否可以在没有睡眠命令的情况下每30秒运行一次cron作业?


4
你打算做什么 cron是用于此的正确工具吗?
Manuel Faux

好问题。
Preet Sangha,

例如,我目前正在使用cron更改我的桌面背景图片,以规避本机背景图像切换器的限制(而不是进入子目录)。如果我想每分钟切换一次多于一次,那我就会遇到这个cron限制。(尽管本地bg切换器具有相同的限制)
donquixote16年

Answers:


36

如果您的任务需要经常运行,那么cron是错误的工具。除了它根本不会频繁启动作业外,如果作业运行的时间比两次启动之间的间隔长,那么您还可能会面临一些严重的问题。重写您的任务以使其守护进程持续运行,然后在必要时从cron启动它(同时确保它已经运行时不会重新启动)。


18
“如果作业的运行时间比两次发射的间隔时间长,您还将冒一些严重问题的风险”。是不正确的,如果是的话,它将同样适用于每5分钟,每小时或每月运行一次的作业。该问题具有解决方案(使用pidfile或其他方法,并在运行作业之前检查该作业是否已在运行)。因此,问题在于cron不允许这种频率出现,但是每隔不到一分钟执行一次任务就存在本质上的错误。
matteo 2012年

2
我的意思是如果您不使用pidfile。如果您的作业每隔X分钟运行一次,并且花费的时间超过X分钟,那么最终您将堆积工作。如果您的工作还受到某种资源(CPU,网络/磁盘带宽等)的限制,那么一次运行更多的资源将需要更长的时间才能完成工作,最终您的计算机将变成混乱的混乱局面。
duskwuff 2012年

2
您可以run-one用来确保程序甚至PHP脚本都不会启动重复的实例。sudo apt-get install run-one并致电run-one <normal command>
kouton

3
正如答案进一步显示的那样,尽管有点骇人听闻,但很有可能。为什么您做错了!!!当它根本不回答问题时,这里接受的答案?
某人

@Mantriur因为问题的作者发现它很有帮助,并将其标记为已接受的答案?:)但是,认真地说,您已经亲自发现了问题:许多其他现代答案都提出了拙劣的解决方案,这些解决方案在生产系统中使用是不明智的。(此外,请记住,其他几个答案仅在提出问题后几年才出现,因此尚无法接受!)
duskwuff 2015年

37

最有创意地 滥用 Linux命令的候选者:

nohup watch -n 30 --precise yourprog >/dev/null &

如果yourprog包含:

date +%M.%S.%N >> yourprog.out

那么yourprog.out可能看起来像:

50.51.857291267
51.21.840818353
51.51.840910204
52.21.840513307
52.51.842455224
53.21.841195858
53.51.841407587
54.21.840629676

表示相当不错的精度。

这是命令部分的说明:

  • nohup-这样可以防止watch在终端退出时跟随其后的命令退出。
  • watch-该程序反复运行命令。通常,每次watch运行命令时,都会显示该命令的第一个屏幕输出。
  • -n 30-运行命令的间隔。在这种情况下,每三十秒一次。
  • --precise-如果没有此选项,请间隔watch运行命令。有了它,命令的每个开始都尽可能在间隔开始。如果在示例中未指定此选项,由于启动和执行命令()所花费的时间,每次的时间将越来越晚,超过30秒。 yourprog
  • yourprog- watch要执行的程序或命令行。如果命令行包含外壳程序专用的字符(例如空格或分号),则需要用引号引起来。
  • >/dev/null-大于号将正在运行的命令的输出重定向watch到文件 /dev/null。该文件将丢弃写入其中的所有数据。这样可以防止将输出写入屏幕,或者由于nohup正在使用输出,因此可以防止将输出发送到名为的文件nohup.out
  • &-该watch命令在后台运行,并且控制权返回到终端或父进程。

请注意,nohup输出的重定向和&后台控制运算符并非特定于watch

这是示例yourprog脚本的说明:

  • date-输出当前日期和/或时间。它也可以设置它们。
  • +%M.%S.%N-这指定date要使用的输出格式。%M是当前分钟,%S是当前秒,%N是当前纳秒。
  • >> yourprog.out-这会将date命令的输出重定向到名为的文件yourprog.out。大于等于double导致在每次调用时将输出附加到文件,而不是覆盖先前的内容。

编辑

可能会被滥用的另一件事(或可能是合法用途)是systemd计时器。

请参阅systemd / Timers作为cron的替代品,以及Cron vs systemd计时器

我将尽快发布一个示例。


6
我给+1纯脸颊
西蒙斯

2
希望对此答案有更多解释。nohup命令对我来说是新的。互联网告诉我这是忽略挂断信号。这仍然让我感到困惑。
donquixote

2
@donquixote:重要的是要认识到,建议不要将命令作为一个整体来执行,因此请使用“滥用”一词。但是,由于其中包含有用的技术,因此为了为您澄清一些事情,我将尝试介绍一些技巧。在&导致该命令在后台运行,控制返回到紧接在命令提示。使用该nohup命令会使后台进程(在这种情况下为watch)忽略在shell退出(例如关闭终端)时发送的挂断信号。...
丹尼斯·威廉姆森

1
...使用重定向输出>/dev/null会导致输出被丢弃,并阻止创建一个nohup.out文件,否则将在标准输出为终端时创建该文件。
丹尼斯·威廉姆森

1
@donquixote:距离现在不止30秒,每30秒一次。剩下的就是让它在后台无人看管地运行,使其更像cron。如果要使用sleep,则需要编写一个循环,以便重复该过程(watch对您来说也是重复一次cron)。您仍然需要nohup&。另一个问题sleep是时间漂移。该--precise的选项watch避免了这一点。如果没有它或sleep在循环中使用,则在时间间隔中加上了要运行的命令或脚本所花费的时间,因此每次运行的时间都晚于……
Dennis Williamson

13

Cron被设计为每分钟都会醒来,因此如果没有一些黑客攻击(例如像您提到的那样睡觉)是不可能做到的。


10
* * * * * /path/to/program
* * * * * sleep 30; /path/to/program

不要忘记在程序中写一些东西,这样如果先前的实例已经在运行,它就会退出。

#!/bin/sh

if ln -s "pid=$$" /var/pid/myscript.pid; then
  trap "rm /var/pid/myscript.pid" 0 1 2 3 15
else
  echo "Already running, or stale lockfile." >&2
  exit 1
fi

当然,这仍然留下了很小的失败机会,因此请搜索google以找到适用于您的环境的更好的解决方案。


有人问:without a sleep command
philippe 2015年

10
发现此问题的其他访问者不在乎是否使用sleep命令:)
donquixote

8

您可以使用第三方软件执行此操作。

一个对我来说效果很好的选择是频繁cron

它允许毫秒精度,并且使您可以选择推迟下一次执行,直到当前执行退出为止。


1
Frequent-cron对我们也很有效,并为我们的许多生产系统提供了动力。我们从来没有遇到过问题。
2013年

2

我有几个问题:

(1)有时系统忙碌而无法在30秒点上完全启动事情,那么有可能同时运行一个作业而弹出另一个作业,然后您有2个(或更多)作业在执行事情。根据脚本的不同,此处可能会有一些重大干扰。因此,在这种脚本中编码应包含一些代码,以确保给定脚本的仅一个实例在同一时间运行。

(2)该脚本可能会有很多开销,并且消耗比您所需更多的系统资源。如果您要与许多其他系统活动竞争,那么这是正确的。

因此,正如一位发布者所言,在这种情况下,我将认真考虑放入一个运行有其他进程的守护程序,以确保它对您的操作至关重要时可以继续运行。


1

我最简单,最喜欢的解决方案:

cron条目:
* * * * * flock -w0 /path/to/script /path/to/script

脚本:
while true;do echo doing something; sleep 10s;done

懒惰的替代::)

* * * * * flock -w0 /path/to/log watch -n 10 echo doing >> /path/to/log

要么

* * * * * flock -w0 /path/to/log watch -n 10 /path/to/script

优点

  • 使用flock命令避免了同时在多个实例中运行脚本。在大多数情况下,这可能非常重要。
  • flockwatch命令可用于大多数Linux安装

缺点

  • 停止这种“服务”需要两个步骤
    • 注释掉cron条目
    • 杀死脚本或watch命令

2
有人可以向Linux新手解释这点吗?谢谢..
a20

@asvany我想我喜欢这种解决方案,但是作为a20,您能为Linux“绿色”发表一些解释吗?ty。
JoelAZ

0

一个解决方案,如果是用于您自己的脚本或可以包装的话:

  1. 获取并记住开始时间。
  2. 如果存在您稍后将要触摸的锁定文件,并且脚本没有运行60秒钟,请稍等片刻,然后再次检查。(例如,在/睡眠中)*
  3. 如果60秒钟后仍存在锁定文件,请退出并显示陈旧的锁定警告。
  4. 触摸锁定文件。
  5. 当脚本未运行60秒钟时,请以所需的睡眠时间循环实际任务。
  6. 删除锁定文件。
  7. 加入每分钟cron。
  8. 鲍勃是你的叔叔。

与构建和监视守护程序相比,它更让人头疼。

*如果您使用的是PHP,请记住clearstatcache()。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.