【问题标题】:What is the best way to run a PHP script at a particular time?在特定时间运行 PHP 脚本的最佳方式是什么?
【发布时间】:2013-02-14 02:03:56
【问题描述】:

我有一个网站,拍卖会在不同的时间结束。拍卖结束后,我需要向卖家和买家发送一封自动电子邮件,以通知他们拍卖结束和结果。显然,我真的不能等待有人加载页面来运行脚本,那么有没有一种好方法可以通过检查当前时间并将其与拍卖结束的时间进行比较并运行该脚本来自动执行此操作?

该站点位于 UNIX 服务器上,因此可以选择 cron 作业,但我担心运行这样的 cron 作业会给服务器带来相当大的负载。

【问题讨论】:

  • 请问您正在运行什么样的服务器基础架构?我认为您在 PHP 以外的其他东西中使用了计时器机制?如果您正在使用其他东西,我建议您将一些代码附加到该计时器机制上,该机制还会在计时器运行时执行邮件发送脚本。
  • 我不知道我可以使用任何类型的计时器,除了页面上运行的 javascript。我不想使用 javascript,因为我实际上害怕有人操纵它并在拍卖中作弊。
  • 那么您使用什么来确定谁赢得了拍卖?您如何能够(精确地)确定谁获胜?我会非常小心地在后端使用强大的计时器机制(例如在 Node.js 或 Perl 或 Python 中的 JavaScript 中......或者除了 PHP 之外的 anything)。我开始了解您的计时器是如何工作的,在用户访问页面时被触发并检查文件/数据库?现在听起来可能很困难,也可能没有必要,但是随着应用程序的增长,您会非常很高兴您在后台创建了一个运行所有这些机制的核心计时器。
  • 是的,但是页面设置为每 60 秒刷新一次。您对如何实现这一点有任何建议吗?现在我有一个拍卖结束日期和时间,当页面加载时,它会根据当前日期和时间检查。
  • 忠告:永远不要相信你的客户会做关键的工作。在这种情况下,为了快速解决问题,我要做的是创建一个 Perl 脚本(因为我们只选择了一个我们知道如何编写的脚本),它可以访问拍卖数据库并包含所有拍卖的“心跳”,这意味着它会跟踪系统时间和所有拍卖的结束。然后,当拍卖结束时,它会连接到一个专门编写的本地网页,该网页使用 PHP 进行所有电子邮件和数据库排序。这个解决方案不是最好的,但它是一个快速的解决方案,并且不再依赖客户端来获取重要的东西。

标签: php unix cron


【解决方案1】:

一个 cron 作业每分钟最多运行一次。

它在服务器上生成的负载实际上取决于您要运行的脚本类型。顺便说一句,我假设您正在使用 cli 运行脚本(而不是仅仅执行 curl http://mysite.com

如果您的脚本花费的时间超过一分钟(您应该对此进行监控),只需:

  • 增加运行之间的间隔时间,或者,
  • 使用lock file 确保您的脚本没有两个实例可以同时运行。

    if (($fp = fopen('/tmp/mylockfile', "r+")) === false) {
        die("Could not open lock file");
    }
    if (!flock($fp, LOCK_EX | LOCK_NB)) {
        die("Could not obtain lock");
    }
    // run your code here
    
    // release the lock and close file
    fclose($fp);
    

OTOH 如果脚本需要每分钟运行一次以上,您将需要完全不同的机制。

【讨论】:

  • '你应该对此进行基准测试',不!你应该确保你的脚本在 59 秒后停止!
  • @hek2mgl 笏?你知道那是多么不切实际,对吧?当然,除非你是在开玩笑。
  • 不需要这个!我已经做到了..有一个队列..在队列结束或 50 秒后停止。如果达到 50 秒 -> 向管理员发送电子邮件。警报! .干得好
  • 不活泼,意味着不容易受到竞争条件的影响,顺便说一句,您的答案是 ok(现在)。但@L0j1k 被否决的答案也是如此。不知道为什么投反对票
  • 建议锁定是处理该问题的好方法,只要您只希望单个进程执行操作即可。如果您需要横向扩展,这还不够。
【解决方案2】:

问:在特定时间或间隔运行 PHP 脚本的最佳方式是什么?
答:使用cron

问:cronjob 是否会给服务器带来很大的负载?
A:当然取决于你的剧本。但是检查是否应该关闭拍卖,关闭它并发送两封电子邮件应该不难。请务必创建某种锁定文件以确保 如果您的脚本运行时间超过设置的时间间隔,它不会运行两次。

问:以小于 1 分钟的间隔运行脚本
A:不能为你回答这个问题。对不起:)

【讨论】:

    【解决方案3】:

    使用 Cron。它允许您每分钟最多运行一次任何命令:http://clickmojo.com/code/cron-tutorial.html

    就服务器负载而言,除非您在非常低端的服务器上经常运行大量数据库调用,否则通常不会有问题。我说的是笼统,但想法是合理的。

    如果您使用其他东西(除了 PHP)来运行您的拍卖计时器机制,我建议您将一些代码附加到该计时器机制,当计时器运行到零并确定获胜者时,该机制还会执行邮件发送脚本。

    【讨论】:

    • OP 说:cron 作业是一种选择,但我担心运行这样的 cron 作业会给服务器带来相当大的负载。如果您想知道,这不是我的反对票。
    • 这不是我的反对票,但可能是因为您说“任何时候都可以”。这不是真的,最多间隔1分钟。对于拍卖,这并不方便。
    • 对,所以执行选项:使用cron。对不起,你不明白。
    • 这是我的担心。如果站点使用量增加,发送电子邮件可能会使服务器变得很麻烦。我担心每个 cron 作业可能有 100 封电子邮件......但如果脚本每个脚本发送 1 封电子邮件(而不是 100 封密件抄送),它们会同时发送吗?
    • 好的,谢谢您的帮助。
    【解决方案4】:

    将 PHP 脚本作为命令行脚本运行。这不会给网络服务器带来负担 - 只是给服务器带来负担,您可以通过 CRON 轻松运行它。

    如果将#!/usr/bin/php添加到脚本的顶部,并用chmod +x scriptname.php更改文件上的执行位,则可以直接执行脚本而无需通过php传递它

    http://php.net/manual/en/features.commandline.php

    【讨论】:

    • 好吧,#!/usr/bin/php 实际上确实通过 PHP 传递,但直接传递给解释器。
    • 对不起,我指的是通过 php scriptname.phpscriptname.php 运行它
    【解决方案5】:

    您需要这样做:

    1. 在您的拍卖信息中存储一些内容,表明您是否已发送此电子邮件(可以是布尔值或发送日期,可能为空)。尽管我不得不假设您除了发送这封电子邮件之外还需要做一些事情吗?喜欢将拍卖标记为已结束,这样就不能再进行竞标了吗?

    2. 查找需要发送此电子邮件的拍卖的一段代码:例如他们已经结束,还没有被提醒。

    3. 重复执行 2 中的代码位。您可以使用 cron。或者,您可以为 unix 编写一个非常简单的守护程序,该守护程序在循环中不断运行(等待至少几毫秒或更长时间;做一些事情)。后者的工作量更大,但在我看来,规模要好得多。如果您对这种方法感兴趣,请参阅http://pear.php.net/package/System_Daemon 了解一些有用的工具。

    要考虑的一件事是,您需要非常小心地避免意外重复发送这封电子邮件。如果您只在单个线程中运行此代码,这很容易,但如果您想要构建到拥有多个不同的分布式机器来创建和发送这些电子邮件的地步,您必须更加小心。如果你是用 cron 来运行它,你能保证它的一次运行总是在另一次开始之前完成吗?

    【讨论】:

      猜你喜欢
      • 2022-06-15
      • 2019-09-24
      • 2015-10-12
      • 1970-01-01
      • 1970-01-01
      • 2016-11-13
      • 2011-05-03
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多