【问题标题】:Linux: schedule command at a specific, different predetermined time every dayLinux:每天在特定的、不同的预定时间安排命令
【发布时间】:2017-08-29 10:56:00
【问题描述】:

我必须每天在不同的时间运行一个命令。时间是预先知道的,并以熟悉的YYYY-MM-DD HH:MM:SS 格式保存在 MySQL 数据库中。

我的想法:

  1. cron 将作业安排在第一天的准确时间,然后让脚本自己修改crontab 条目,并为第二天提供正确的时间。

  2. cron大约正确的时间安排作业,然后让它从数据库中读取准确的时间并在此之前休眠。

  3. cron每分钟调度一次作业执行,留给脚本判断当前日期/时间是否对应正确的执行时间;是则执行,否则退出。

  4. at 在第一天用at 提交作业,然后让它从数据库中读取第二天的时间,然后用at 重新提交。

其他信息:

该命令是一个 PHP 脚本,它编写当天的消息并将其发送给所有注册到该网站的用户。如果他们更好地解决这个问题,我可以考虑其他技术。我想保留重新启动服务器的能力(在预期的执行时间之外),而不必太担心工作会丢失,因此解决方案 1.3. 在这方面看起来更好。我从在一天中的两个不同时间运行的两个命令开始,但我很快就会在每天的不同时间安排几十个类似的作业,所以我希望尽可能避免混乱.此时我可能会选择3

问题: 是否有更好/首选/既定的方式来完成这项任务?欢迎使用上述以外的解决方案。我应该注意(您推荐的解决方案的)主要缺点是什么?

【问题讨论】:

  • 没有 cron 作业可以精确地运行脚本,您将获得的最小尺寸是小时。小时从系统启动时开始,并从那时起重复。你应该寻找anacron 或类似的。
  • @suleiman 我认为cron 可以在指定的时间运行命令,精度为一分钟。为什么你会推荐anacron?我读到“Anacron 是台式机和笔记本电脑的 cron,并且不希望系统像服务器一样运行 24 x 7。”我正在运行一个服务器,它通常是 24x7 的。
  • @suleiman 我相信你这样说是错误的。最小间隔是一分钟,您可以指定一天中的精确时间,因此,关于它开始计算小时数的方式的考虑也是错误的。
  • 我的玉米文件夹是:/etc/cron.daily cron.hourly cron.monthly and cron.weekly 没有别的。

标签: mysql linux job-scheduling ubuntu-server


【解决方案1】:

我相信您需要构建您的自定义应用程序来实现您想要实现的逻辑。

最终您可以使用 cron 系统来启动进程或确保进程正在运行(以防它死亡或被杀死)。

我要做的就是编写一个自定义的 PHP 程序(或 python 或你的名字)来执行以下操作:

  • 打开与 DB 的连接
  • 检查计划下一次执行的时间
  • 计算是否到了运行时间
  • 如果没有,它会休眠 X 秒(这取决于您的偏好)
  • 是时候运行了,它履行职责
  • 再次休眠,循环开始

另一种方法是检查每次执行计划,以检查计划中的更改。

另一个将被读取一次并休眠直到执行时间,但在另一种情况下,您将无法捕获调度中的更改

这一切都取决于你,总而言之,这个程序非常简单

【讨论】:

  • 您还可以查看是否通过 cron 脚本设置了执行时间,然后通过 at 命令安排运行并删除/删除数据库中的开始时间。如果 cronjob 找到新的开始时间,他们会再次执行。 linux.die.net/man/1/at
  • 感谢您的回答。请说明此解决方案相对于上述选项3. 的任何优势。它确实增加了一层复杂性,以另一个脚本的形式,应该被监控并一直运行。我认为最好依靠现有的计划而不是实施我自己的计划,除非有明显的优势。另一方面,与其他技术相比,我一直认为 PHP 不适合无休止的任务。否则请告知。
  • @BerndBuffen 您提到的是对答案的一个很好的补充,我肯定会考虑它如果我沿着实现自己的调度程序的路线前进。与其删除记录,不如将其标记为已执行。
【解决方案2】:

我最终使用了上面的解决方案3.,到目前为止我对它非常满意。

所有逻辑都在.php文件中,负责:

  1. 将当前日期/时间保存在变量中(例如$now
  2. 对其进行任何考虑
  3. 扫描数据库以搜索匹配的日期/时间

这实际上允许了合理程度的灵活性:

  1. 如果某个信号量文件存在,我可以选择不运行任何命令:

    if (file_exists($filename)) {exit;}
    
  2. 我可以在选项文件中设置参数,例如启用调试或测试模式:

    include parameters.php
    if ($debug === true) {error_reporting(E_ALL);}
    
  3. 如果是元旦,我可以避免打扰用户:

    if (date('m-d') == '01-01') {exit;}
    
  4. 我可以根据自定义逻辑引入延迟:

    if (date('w', strtotime($now)) === '0') {$now = date('Y-m-d H:i:s', strtotime($now . ' +15 minutes'));}
    

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-05-09
    • 1970-01-01
    • 2013-02-10
    • 1970-01-01
    • 1970-01-01
    • 2016-11-24
    • 1970-01-01
    • 2022-01-24
    相关资源
    最近更新 更多