【问题标题】:Create cronjob with Zend Framework使用 Zend 框架创建 cronjob
【发布时间】:2010-09-13 16:29:00
【问题描述】:

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

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

[更新]

我想我解释得还不够。

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

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

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

【问题讨论】:

    标签: php zend-framework cron command-line-interface


    【解决方案1】:

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

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

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

    祝你好运!

    【讨论】:

      【解决方案2】:

      对于 Zend 框架,我目前正在使用下面列出的代码。该脚本仅包含门户文件 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
      

      【讨论】:

        【解决方案3】:

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

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

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

        为了完成我的工作,我只需要一个简单的 crontab 条目,它每 5 分钟运行一次,它会访问 heartbeat.php。到目前为止,它在两个不同的网站上都表现出色。

        【讨论】:

        • 我也在考虑滥用问题,但找到了一个简单的解决方案。通过只允许一些 IP 运行 cronjob(在我的情况下只有 127.0.0.1),我得到了我需要的安全性。全局 cronjob 类是一个有趣的想法 :)
        【解决方案4】:

        几天前有人在 fw-general 上提到了this blog entry(我建议您在使用 Zend 框架时阅读mailinglist)。

        还有一个Zend_Controller_Request_Cli 的提案,迟早会解决这个问题。

        【讨论】:

        【解决方案5】:

        我可以访问专用服务器,并且我最初对 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,因此总是有这个警告。您可以通过多种不同方式找到解决方案。

        【讨论】:

          【解决方案6】:

          看看zf-cli

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

          【讨论】:

            【解决方案7】:

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

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

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

            【讨论】:

              【解决方案8】:

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

              【讨论】:

                【解决方案9】:

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

                【讨论】:

                • 我正在寻找可以在 windows 和 linux 上运行而没有太大变化的东西,所以一切都必须在 php 中
                【解决方案10】:

                我用this post 扩展了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();
                }
                

                感谢格雷戈!

                【讨论】:

                  【解决方案11】:

                  我的解决方案:

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

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

                  【讨论】:

                    【解决方案12】:

                    这是我使用 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。我在这里找到了这个新路由器:Setting up Cron with Zend Framework 1.11

                    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
                    

                    【讨论】:

                      【解决方案13】:

                      在同一目录或 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 是你可以做你的工作的动作,同样,不需要运行引导文件等。

                      【讨论】:

                        猜你喜欢
                        • 1970-01-01
                        • 1970-01-01
                        • 1970-01-01
                        • 2011-08-06
                        • 2012-04-23
                        • 2013-02-11
                        • 2014-08-02
                        • 2011-11-17
                        • 1970-01-01
                        相关资源
                        最近更新 更多