22

我正在尝试编写一个 cronjob 控制器,所以我可以调用一个网站并执行所有模块 cronjob.php。现在我的问题是我该怎么做?

curl 是一种选择,所以我也可以计算错误和成功吗?

[更新]

我想我解释得还不够。

我想要做的是有一个文件,我可以从http://server/cronjob调用它,然后让它执行每个 /application/modules/*/controller/CronjobController.php 或者有另一种方式来做所有的cronjobs 不在一个地方,而是在模块所在的同一个地方。这会给我带来好处,如果一个模块不存在,它就不会尝试运行它的 cronjob。

现在我的问题是您将如何执行所有模块 CronjobController 或者您会以完全不同的方式执行它以便它仍然保持模块化?

我希望能够给出有多少 cronjobs 成功运行,有多少没有

4

13 回答 13

12

经过一些研究和大量拖延,我得出了一个简单的结论,即 ZF 化的 cron 脚本应该包含您 zend 框架应用程序的所有功能 - 没有所有视图的东西。我通过在我的应用程序目录中创建一个新的 cronjobfoo.php 文件来实现这一点。然后我从以下方面获取了最低限度: -my front controller (index.php) -my bootstrap.php

我拿出了所有的视图材料,专注于保持环境设置、数据库设置、自动加载器和注册表设置。我不得不花一点时间来更正文档根变量并删除从我的引导程序中复制的一些 OO 功能。

在那之后我只是编码了......在我的情况下,它正在编译并通过电子邮件发送夜间报告。使用 Zend_Mail 很棒。当我确信我的脚本按我想要的方式运行时,我只是将它添加到我的 crontab 中。

祝你好运!

于 2009-07-16T15:31:48.643 回答
10

对于 Zend Framework,我目前正在使用下面列出的代码。该脚本仅包含门户文件 index.php,其中引导所有路径、环境和其他 Zendy 代码。通过在 cron 脚本中定义一个常量,我们取消了运行应用程序的最后一步。

这意味着应用程序只是设置,甚至没有引导。在这一点上,我们开始引导我们需要的资源,那就是

//public/index.php

if(!defined('DONT_RUN_APP') || DONT_RUN_APP == false) {  
    $application->bootstrap()->run();
}

// application/../cron/cronjob.php

define("DONT_RUN_APP",true);
require(realpath('/srv/www/project/public/index.php'));
$application->bootstrap('config');
$application->bootstrap('db');

//cron code follows
于 2009-08-12T20:45:20.367 回答
7

我会警告将您的 cronjobs 向公众开放,因为它们可能会在正常时间之外触发,并且取决于它们的工作,会导致问题(我知道这不是您想要的,但是通过将它们放入实际的控制器中,它变得可以访问从浏览器)。例如,我有一个发送电子邮件的 cron。如果有人找到 cron URL 并开始点击它,我会不断收到垃圾邮件。

我所做的是创建一个 cron 文件夹,并在其中创建了一个 heartbeat.php,它为我引导 Zend 框架(减去 MVC)。它检查一个数据库,其中包含所有已安装的 cron 作业的列表,如果该运行它们,则生成 cron 作业类的实例并运行它。

cron 作业只是抽象 cron 类的子类,具有 install()、run()、deactivate() 等方法。

为了启动我的工作,我只有一个简单的 crontab 条目,它每 5 分钟运行一次,它会访问 heartbeat.php。到目前为止,它在两个不同的站点上运行良好。

于 2008-09-27T13:44:35.607 回答
3

我可以访问专用服务器,并且最初对 cron 作业有不同的引导程序。我最终讨厌这个想法,只是希望我可以在现有的 MVC 设置中做到这一点,而不必费心移动东西。

我创建了一个文件 cron.sh,保存在我的站点根目录(非公开)中,并在其中放置了一系列我想运行的命令。因为我想一次运行许多命令,所以我像往常一样在我的控制器中编写了 PHP,并在 cron.sh 中为这些 url 添加了 curl 调用。例如curl http://www.mysite.com/cron_controller/action然后在我运行的 cron 界面上bash /path/to/cron.sh

正如其他人指出的那样,任何猜到 url 的人都可以解雇您的 crons,所以总是有这个警告。您可以通过许多不同的方式找到解决方案。

于 2011-11-11T17:35:00.120 回答
3

几天前有人在 fw-general 上提到了这个博客条目(我建议您在使用 Zend 框架时阅读该邮件列表)。

Zend_Controller_Request_Cli也有一个提议,迟早会解决这个问题。

于 2008-09-27T14:42:32.207 回答
1

为什么不直接创建一个 crontab.php,包括或需要 index.php 引导文件?

考虑到引导程序正在执行Zend_Loader::registerAutoload(),您可以直接开始使用模块,例如,myModules_MyClass::doSomething();

这样你就跳过了控制器。Controller的工作是通过http控制访问。在这种情况下,您不需要控制器方法,因为您是在本地访问。

于 2009-04-09T07:19:09.267 回答
1

看看zf-cli

这可以很好地处理所有 cron 作业。

于 2010-12-18T11:29:34.950 回答
0

您是否具有对模块目录的文件系统访问权限?您可以遍历目录并确定 CronjobController.php 可用的位置。然后您可以使用Zend_Http_Client通过 HTTP 访问控制器或使用类似的方法Zend_Test_PHPUnit:在本地模拟实际的调度过程。

于 2008-09-27T19:01:23.753 回答
0

您可以设置一个数据库表来保存对 cronjob 脚本(在您的模块中)的引用,然后使用 exec 命令并在通过/失败时返回值。

于 2008-09-28T02:30:04.703 回答
0

这是我使用 Zend Framework 运行 Cron 作业的方式

Bootstrap中,我将保留环境设置,因为它减去 MVC:

public static function setupEnvironment()
{
     ...
     self::setupFrontController();
     self::setupDatabase();
     self::setupRoutes();
     ...
     if (PHP_SAPI !== 'cli') { 
          self::setupView();
          self::setupDbCaches();
     }
     ...
}

同样在 Bootstrap 中,我将修改 setupRoutes 并添加自定义路由:

public function setupRoutes()
{   
    ...
    if (PHP_SAPI == 'cli') { 
        self::$frontController->setRouter(new App_Router_Cli());
        self::$frontController->setRequest(new Zend_Controller_Request_Http());        
    }
}

App_Router_Cli是一种新的路由器类型,它根据这种类型的请求确定控制器、操作和可选参数:script.php controller=mail action=send. 我在这里找到了这个新路由器:使用 Zend Framework 1.11 设置 Cron

class App_Router_Cli extends Zend_Controller_Router_Abstract 
{
    public function route (Zend_Controller_Request_Abstract $dispatcher) 
    {
        $getopt = new Zend_Console_Getopt (array());
        $arguments = $getopt->getRemainingArgs();
        $controller = "";
        $action = "";
        $params = array();

        if ($arguments) {

            foreach($arguments as $index => $command) {

                $details = explode("=", $command);

                if($details[0] == "controller") {
                    $controller = $details[1];
                } else if($details[0] == "action") {
                    $action = $details[1];
                } else {
                    $params[$details[0]] = $details[1];
                }
            }

            if($action == "" || $controller == "") {
                die("Missing Controller and Action Arguments == You should have: 
                     php script.php controller=[controllername] action=[action]");
            }
            $dispatcher->setControllerName($controller);
            $dispatcher->setActionName($action);
            $dispatcher->setParams($params);

            return $dispatcher;
        }
        echo "Invalid command.\n", exit;
        echo "No command given.\n", exit;
    }

    public function assemble ($userParams, $name = null, $reset = false, $encode = true)
    {
        throw new Exception("Assemble isnt implemented ", print_r($userParams, true));
    }
}

CronController我做了一个简单的检查:

public function sendEmailCliAction()
{   
    if (PHP_SAPI != 'cli' || !empty($_SERVER['REMOTE_ADDR'])) { 
        echo "Program cannot be run manually\n";
        exit(1);
    } 
    // Each email sent has its status set to 0;

crontab 运行这种命令:

    * * * * * php /var/www/projectname/public/index.php controller=name action=send-email-cli >> /var/www/projectname/application/data/logs/cron.log
于 2012-07-27T11:36:50.167 回答
0

我用这篇文章扩展了 gregor 的答案。这是出来的:

//public/index.php 

// Run application, only if not started from command line (cli)
if (php_sapi_name() != 'cli' || !empty($_SERVER['REMOTE_ADDR'])) {
    $application->run();
}

谢谢格雷戈!

于 2011-01-13T01:32:03.690 回答
0

我的解决方案:

  • 卷曲/cron
  • 全局 cron 方法将 include_once 所有控制器
  • 检查每个控制器是否有 ->cron 方法
  • 如果有,请运行它们。

公共 cron url(用于 curl)不是问题,有很多方法可以避免滥用。如前所述,检查远程 IP 是最简单的。

于 2011-05-09T08:52:34.233 回答
0

在同一目录或 cron 作业文件夹中运行引导程序是没有意义的。我创建了一种更好、更简单的方法来实现 cron 作业。请遵循以下事项,以使您的工作变得轻松而智能:

  1. 随心所欲地创建一个 cron 作业文件夹,例如“cron”或“crobjob”等。

  2. 有时我们需要 cron 作业在不同间隔的服务器上运行,例如 1 小时间隔或 1 天间隔,我们可以在服务器上设置。

  3. 在 cron 作业文件夹中创建一个文件,就像我创建了一个“init.php”一样,现在假设您想每天向用户发送一份时事通讯。您不需要在 init.php 中执行 zend 代码。

  4. 因此,只需在 init.php 中设置 curl 函数,并在该 curl 函数中添加控制器操作的 URL。因为我们的主要目的是每天都应该调用一个动作。例如,URL 应该是这样的:

https://www.example.com/cron/newsletters

所以在 curl 函数中设置这个 URL 并在同一个文件的 init.php 中调用这个函数。

在上面的链接中,您可以看到“cron”是控制器,而 newsletters 是您可以完成工作的操作,同样,不需要运行引导文件等。

于 2019-04-13T07:26:24.843 回答