2008-09-27 102 views
20

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

卷曲是一个选项,所以我也可以算错误和成功?

[更新]

我想我没有足够的解释。

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

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

而且我希望能够giveout多少cronjobs成功运行,并且有多少没

回答

6

我要提醒把你cronjobs向公众开放的,因为他们可以正常的时间之外触发,并根据他们做什么,导致问题(我知道这不是你想要的,但是通过将它们放入实际的控制器中,它可以从浏览器访问)。例如,我有一个发送电子邮件的cron。如果有人发现cron URL并刚刚开始触发它,我会被不断发送垃圾邮件。

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

的cron作业是从抽象的cron类,它具有像安装(),运行(),停止()方法等只是子类

要火了我的工作,我只是有一个简单的crontab条目每5分钟运行一次heartbeat.php。到目前为止,它在两个不同的网站上工作得很好。

+0

我思考滥用的东西,但已经到了一个简单的解决方案。通过只允许一些IP运行cronjob(在我的情况下只是127.0.0.1)我得到我需要的安全.. 全球cronjob类是一个interessting想法:) – Thomaschaaf 2008-09-27 14:23:01

2

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

还有一个建议Zend_Controller_Request_Cli,应该迟早解决这个问题。

+0

我也喜欢这个解决方案。在我的博客上查看此脚本的更新版本:http://webdevbyjoss.blogspot.com/2010/09/running-zend-framework-application-from.html – webdevbyjoss 2011-09-22 15:11:52

0

你有文件系统访问模块的目录吗?您可以迭代目录并确定CronjobController.php的可用位置。然后,您可以使用Zend_Http_Client通过HTTP访问控制器,也可以使用类似Zend_Test_PHPUnit的方法:在本地模拟实际调度过程。

0

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

+0

我正在寻找一些可以在windows和linux上工作的东西改变,所以一切都必须在PHP中 – Thomaschaaf 2008-09-28 08:00:35

1

为什么不只是创造一个crontab.php,包括,或要求的index.php引导文件?

考虑到引导正在执行Zend_Loader::registerAutoload(),你就可以开始直接与模块的工作,例如,myModules_MyClass::doSomething();

你跳过控制器的方式。控制器作业是通过http控制访问。在这种情况下,您不需要控制器方法,因为您正在本地访问。

12

一些研究,我来简单的结论,你的Zend Framework应用程序一个ZF-美化版的cron脚本应该包含所有的功能,很多拖延之后 - 没有所有的观点的东西。我通过在我的应用程序目录中创建一个新的cronjobfoo.php文件来完成此任务。然后,我把最起码的: -My前端控制器(index.php文件) -My bootstrap.php中

我拿出所有的视图的东西,专注于保持环境的设置,DB设置,自动加载机,&注册表建立。我不得不花一点时间来纠正文档根变量,并删除从引导程序复制的一些OO功能。

之后,我只是编码的路程。在我的情况下,它被编译并通过电子邮件发送出去夜间报告。使用Zend_Mail真是太棒了。当我确信我的脚本以我想要的方式工作时,我只是将它添加到了我的crontab中。

祝你好运!

9

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

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

//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 
0

我伸出格雷戈尔答案与this post。这一下就出来了:

//public/index.php 

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

感谢格雷戈尔!

0

我的解决办法:

  • 卷曲/ cron的
  • 全球的cron方法include_once所有控制器
  • 检查每个controllors是否有 - > cron的方法
  • 如果他们有,运行这些。

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

2

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

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

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

0

这是我的方式来与Zend框架运行cron任务

引导我会保持环境设置,因为它是零下MVC:

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

此外,在引导,我将修改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