2008-09-27 35 views
20

Estoy tratando de escribir un controlador cronjob, así que puedo llamar a un sitio web y ejecutar todos los módulos cronjob.php. Ahora mi problema es ¿cómo hago eso?Crear cronjob con Zend Framework

¿Sería curl ser una opción, entonces también puedo contar los errores y éxitos?

[Actualización]

supongo que no he explicado lo suficiente.

Lo que quiero hacer es tener un archivo al que pueda llamar como http://server/cronjob y luego hacer que ejecute cada /application/modules/*/controller/CronjobController.php o tener otra forma de hacerlo así que todos los cronjobs aren en un lugar pero en el mismo lugar donde se encuentra el módulo. Esto me ofrecería la ventaja de que si un módulo no existe no intenta ejecutar su cronjob.

Ahora mi pregunta es ¿cómo ejecutarías todos los módulos CronjobController o lo harías de una manera completamente diferente para que siga siendo modular?

y quiero ser capaz de giveout cuántos cronjobs han ejecutado correctamente y cómo muchos no

Respuesta

6

yo advertiría poner sus cronjobs accesibles al público, ya que podrían ser provocados fuera de sus tiempos normales y, dependiendo de lo que hacen, causa problemas (sé que eso no es lo que pretendes, pero poniéndolos en un controlador real se vuelve accesible desde el navegador). Por ejemplo, tengo un cron que envía correos electrónicos. Me enviarían spam constantemente si alguien encontraba la URL de cron y simplemente comenzaba a pegarla.

Lo que hice fue crear una carpeta cron y allí creó un heartbeat.php que arranca Zend Framework (menos MVC) para mí. Comprueba una base de datos que tiene una lista de todos los trabajos cron instalados y, si es tiempo de que se ejecuten, genera una instancia de la clase del trabajo cron y la ejecuta.

Los trabajos de cron son sólo las clases hijas de una clase abstracta que tiene cron métodos como la instalación(), run(), desactivar(), etc.

Para disparar mi trabajo yo sólo tienen una entrada crontab sencilla que se ejecuta cada 5 minutos que llega a heartbeat.php. Hasta ahora, funcionó maravillosamente en dos sitios diferentes.

+0

estaba pensando en las cosas de abuso también, pero han llegado a una solución simple. Al solo permitir que algunos IP ejecuten el cronjob (en mi caso solo 127.0.0.1) obtengo la seguridad que necesito ... La clase de cronjob Global es una idea interesante :) – Thomaschaaf

2

Alguien mencionó this blog entry hace un par de días en fw-general (un mailinglist que recomiendo leer cuando utiliza el Zend Framework).

También hay una propuesta para Zend_Controller_Request_Cli, que debería abordar esto tarde o temprano.

+0

Me gusta esta solución también. Ver la versión actualizada de esta secuencia de comandos en mi blog: http://webdevbyjoss.blogspot.com/2010/09/running-zend-framework-application-from.html – webdevbyjoss

0

¿Tiene acceso al sistema de archivos en los directorios de los módulos? Podría iterar sobre los directorios y determinar dónde está disponible un CronjobController.php. Luego, puede usar Zend_Http_Client para acceder al controlador a través de HTTP o usar un enfoque como Zend_Test_PHPUnit: simule el proceso de despacho local de manera local.

0

Puede configurar una tabla de base de datos para contener referencias a los scripts cronjob (en sus módulos), luego use un comando exec con un valor de retorno en aprobado/no aprobado.

+0

Estoy buscando algo que funciona en Windows y Linux sin grandes cambios, entonces todo debe estar en php – Thomaschaaf

1

¿Por qué no acaba de crear un crontab.php, que incluye o requiere el archivo bootstrap index.php?

Teniendo en cuenta que el sistema de arranque está ejecutando Zend_Loader::registerAutoload(), puede empezar a trabajar directamente con los módulos, por ejemplo, myModules_MyClass::doSomething();

De esa manera va a omitir los controladores. El trabajo del controlador es controlar el acceso a través de http. En este caso, no necesita el enfoque de controlador porque está accediendo localmente.

12

Después de algunas investigaciones y mucha procrastinación llegué a la simple conclusión de que una secuencia de comandos cron ZF -ized debería contener toda la funcionalidad de su aplicación Zend Framework, sin todas las cosas de la vista. Lo logré creando un nuevo archivo cronjobfoo.php en mi directorio de aplicaciones. Entonces tomé el mínimo de: controlador -mi frontal (index.php) Bootstrap.php -mi

Saqué todo el punto de vista material y se centró en mantener la configuración del entorno, db configuración, cargador automático, & registro preparar. Tuve que tomarme un poco de tiempo para corregir la variable de raíz del documento y eliminar parte de la funcionalidad de OO copiada de mi bootstrap.

Después de eso me acabo de codificar ... en mi caso fue compilar y enviar informes nocturnos por correo electrónico. Fue genial usar Zend_Mail. Cuando estaba seguro de que mi script funcionaba como yo quería, solo agregué mi crontab.

buena suerte!

9

Para Zend Framework Actualmente estoy usando el código que se describe a continuación. La secuencia de comandos solo incluye el archivo del portal index.php, donde todas las rutas, el entorno y otros códigos de Zendy están iniciados. Al definir una constante en el script cron, cancelamos el paso final, donde se ejecuta la aplicación.

Esto significa que la aplicación solo está configurada, ni siquiera se inicia. En este punto empezamos bootstraping los recursos que necesitamos y es que

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

Extendí la respuesta de gregor con this post. Esto es lo que salió:

//public/index.php 

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

Gracias gregor!

0

Mi solución:

  • rizo/cron
  • método cron Global include_once todos los controladores
  • Comprobar si cada uno de los controllors tiene -> método de cron
  • Si es así, ejecutar esos.

Public cron url (para curl) no es un problema, hay muchas maneras de evitar el abuso.Como se dijo, la comprobación de IP remota es la más fácil.

2

Tengo acceso a un servidor dedicado e inicialmente tenía un programa de arranque diferente para las tareas de cron. Eventualmente odié la idea, deseando poder hacer esto dentro de la configuración de MVC existente y no tener que molestarme en mover las cosas.

Creé un archivo cron.sh, guardado está dentro de la raíz de mi sitio (no es público) y en él pongo una serie de comandos que me gustaría ejecutar. Como quería ejecutar muchos comandos a la vez, escribí el PHP dentro de mis controladores como de costumbre y agregué curl a esas URL dentro de cron.sh. por ejemplo, curl http://www.mysite.com/cron_controller/action Luego en la interfaz cron ejecuté bash /path/to/cron.sh.

Según lo señalado por otros, sus crons pueden ser despedidos por cualquiera que adivine la url así que siempre hay esa advertencia. Puede encontrar una solución a eso de muchas maneras diferentes.

0

Esta es mi forma de correr Cron con Zend Framework

En Bootstrap voy a mantener la configuración del entorno, ya que es menos MVC:

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

También en Bootstrap, me modificará setupRoutes y agregará una ruta personalizada:

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 es un nuevo tipo de enrutador que determina el controlador, la acción y los parámetros opcionales en función de este tipo de solicitud: script.php controller=mail action=send. He encontrado este nuevo router aquí: 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)); 
    } 
} 

En CronController hago una simple comprobación:

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 ejecuta una orden de este tipo:

* * * * * php /var/www/projectname/public/index.php controller=name action=send-email-cli >> /var/www/projectname/application/data/logs/cron.log