Cronjobs

Im Entwickler-Forum können Implementierungsdetails sowie Alternativen der Umsetzung diskutiert werden. // Here, developers can discuss implementation details of features of their projects.
Coach83
Beiträge: 271
Registriert: 13.05.2010, 17:33:12
Kontaktdaten:

Cronjobs

Beitrag von Coach83 » 12.09.2014, 11:12:34

Hallo zusammen,

ich stelle mir gerade die Frage, wie man vorgehen kann auf Seiten, auf denen keine Cronjobs ausgeführt werden dürfen.
Kann ich in der index.php einfach eine FC-Action ausführen, die mir diese beim Aufruf einer Seite einfach ausführt?

Dann könnte ich diese index.php ja auch in meinem Cronjob aufrufen - und danach die Ausgabe beenden, oder?

Benutzeravatar
dr.e.
Administrator
Beiträge: 4536
Registriert: 04.11.2007, 16:13:53

Re: Cronjobs

Beitrag von dr.e. » 12.09.2014, 11:17:37

Hallo Coach,

aus meiner Sicht gibt es zwei Optionen: entweder die von dir vorgestellte oder du schreibst dir einfach eine weitere, parallel zur index.php liegende Datei - z.B. cron.php - und lässt diese über einen Dienst aufrufen. Eine Übersicht findest du z.B. hier: http://www.cronjobservices.com
Kann ich in der index.php einfach eine FC-Action ausführen, die mir diese beim Aufruf einer Seite einfach ausführt?
Na klar! :) Dazu einfach oper registerAction() beim Front-Controller als "permanente" Action (=wird bei jedem Request ausgeführt) bekannt geben. Details dazu unter http://adventure-php-framework.org/Seit ... he-Actions.
Dann könnte ich diese index.php ja auch in meinem Cronjob aufrufen - und danach die Ausgabe beenden, oder?
Das geht dann nur, wenn es eine dynamische Action ist und du die URL-Parameter dort irgendwie rein bekommst (z.B. über einen internen curl-Aufruf). Das ist IMHO aber recht umständlich und ich persönlich würde daher eher eine eigene Datei anlegen und dort (und nur dort) die Logik für den Job einbauen.
Viele Grüße,
Christian

GeneralCrime
Beiträge: 67
Registriert: 14.12.2011, 07:13:16

Re: Cronjobs

Beitrag von GeneralCrime » 08.03.2015, 01:07:12

Also ich hab dies über ein generic:Importdesign gelöst welcher bei bestimmten parametern eine template startet die nur für cronjobs ist.

Benutzeravatar
Paric
Beiträge: 45
Registriert: 25.08.2014, 08:51:04

Re: Cronjobs

Beitrag von Paric » 17.03.2015, 17:09:21

ich hänge mich hier einfach mit dran.

Ich habe auch ein paar Cronjobs, welche ich auf die "neu"-strukturierte Seite übertragen muss. Unter anderem ein Script, welches automatische Antwort-Mails generiert. Jetzt will ich innerhalb dieses scripts die "Mail.php" integrieren per require_once, aber ab da reagiert es nicht mehr.

Ich habe eine cron.php geschrieben, welche wie folgt ausschaut:

Code: Alles auswählen

<?php
$apfClassLoaderConfigurationRootPath = './TELLA';
include('/daten/httpd/tella/APF/APF/core/bootstrap.php');

use APF\core\loader\RootClassLoader;
use APF\core\loader\StandardClassLoader;
use APF\core\singleton\Singleton;
use APF\core\registry\Registry;
use APF\core\configuration\ConfigurationManager;
use APF\tools\request\RequestHandler;

$classLoader = new StandardClassLoader('TELLA', 'TELLA');
RootClassLoader::addLoader($classLoader);

ConfigurationManager::retrieveProvider('ini')->setOmitContext(true);

$fC = Singleton::getInstance('APF\core\frontcontroller\Frontcontroller');

Registry::register('APF\core', 'Environment', 'DEFAULT');

$action = RequestHandler::getValue("action");

$fC->registerAction('TELLA\cron', $action . 'Crontab');
echo $fC->start('TELLA\pres\templates\init', 'dummy'); 
und die dementsprechende Action sieht so aus:

Code: Alles auswählen

<?php
namespace TELLA\crontabs;

use APF\core\frontcontroller\AbstractFrontcontrollerAction;

class faxResponderCrontabAction extends AbstractFrontcontrollerAction
{
    public function __construct()
    {
        $this->type = self::TYPE_PRE_PAGE_CREATE;
    }
    
    public function run()
    {
        require_once ("Mail.php");
        .
        .
        .
    }
}
?>
wie gesagt, ich bekomme gar keine Ausgabe, nichtmal eine Fehlermeldung. Auch im Log steht nix drin...

Beste Grüße,
Pit

Benutzeravatar
dr.e.
Administrator
Beiträge: 4536
Registriert: 04.11.2007, 16:13:53

Re: Cronjobs

Beitrag von dr.e. » 17.03.2015, 21:47:55

Hallo Pit,
ich bekomme gar keine Ausgabe, nichtmal eine Fehlermeldung. Auch im Log steht nix drin...
Hast du mal versucht das error_reporting bzw. display_errors per ini_set() zu definieren? display_errors auf 1 zu setzen sollte zumindest helfe einen Fehler zu sehen.
Viele Grüße,
Christian

Benutzeravatar
Paric
Beiträge: 45
Registriert: 25.08.2014, 08:51:04

Re: Cronjobs

Beitrag von Paric » 18.03.2015, 08:39:53

ja, natürlich :(

ein die() vor dem include (bzw. require_once - kein Unterschied in dem code an der Stelle) macht was es soll, aber nach dem include geht weder eine print-ausgabe noch ein die("...") oder ähnliches.... Und ist auch nicht so das er sich tot-lädt, nein selbst bei einem reload der Seite bricht er in Bruchteilen einer Sekunde ab, und der Browser meldet mir "Keine Daten empfangen" bzw. firefox sagt "Die Verbindung zum Server wurde zurückgesetzt, während die Seite geladen wurde.". Ich bin gerade ziemlich ratlos...

[edit]
einen einfügen in einen funktionierenden Controller ergibt zumindest eine Fehlermeldung, aber auch diese bringt micht nicht weiter:

Code: Alles auswählen

Fatal error: Class 'APF\core\logging\entry\SimpleLogEntry' not found in /storage/disk3/lampp/lib/php/Mail.php on line 55
[edit2]
ok, wir sind einen Schritt weiter. Ich habe mich von require_once entfernt, und in der cron.php einen neuen Class-loader registriert.
Diese siht jetzt wie folgt aus:

Code: Alles auswählen

<?php
$apfClassLoaderConfigurationRootPath = './TELLA';
// require_once ("Mail.php");
include('/daten/httpd/tella/APF/APF/core/bootstrap.php');

use APF\core\loader\RootClassLoader;
use APF\core\loader\StandardClassLoader;
use APF\core\singleton\Singleton;
use APF\core\registry\Registry;
use APF\core\configuration\ConfigurationManager;
use APF\tools\request\RequestHandler;

$classLoader = new StandardClassLoader('TELLA', 'TELLA');
$phpClassLoader = new StandardClassLoader('PHP', '/opt/lampp/lib/php');
RootClassLoader::addLoader($classLoader);
RootClassLoader::addLoader($phpClassLoader);

ConfigurationManager::retrieveProvider('ini')->setOmitContext(true);

$fC = Singleton::getInstance('APF\core\frontcontroller\Frontcontroller');

Registry::register('APF\core', 'Environment', 'DEFAULT');

$action = RequestHandler::getValue("action");

$fC->registerAction('TELLA\biz\actions', 'register-globals');
$fC->registerAction('TELLA\biz\actions', 'register-logs');
$fC->registerAction('TELLA\cron', $action . 'Crontab');
echo $fC->start('TELLA\pres\templates\init', 'dummy'); 
diese implementiere ich nun per

Code: Alles auswählen

use PHP\Mail; 
jetzt bekomme ich die Fehlermeldung

Code: Alles auswählen

Fatal error: Class 'APF\core\logging\entry\SimpleLogEntry' not found in /storage/disk3/lampp/lib/php/Mail.php on line 55
Wieso sucht er die SimpleLogEntry-Klasse in der Mail.php?
Das verwirrt mich :D

Benutzeravatar
dr.e.
Administrator
Beiträge: 4536
Registriert: 04.11.2007, 16:13:53

Re: Cronjobs

Beitrag von dr.e. » 19.03.2015, 12:14:51

Ich vermute, dass dort ein Fehler fliegt und versucht wird ein Log zu schreiben.

Ferner denke ich dass das Class-Loading für die Klasse Mail schief geht.
Viele Grüße,
Christian

Benutzeravatar
Paric
Beiträge: 45
Registriert: 25.08.2014, 08:51:04

Re: Cronjobs

Beitrag von Paric » 19.03.2015, 15:10:08

ja, das ist auch meine Vermutung. Allerdings rede ich hier von einer Klasse, welche von PHP mitgeliefert wird, wo ich also von ausgehen sollte das diese keinen Fehler beinhaltet :/

Benutzeravatar
dr.e.
Administrator
Beiträge: 4536
Registriert: 04.11.2007, 16:13:53

Re: Cronjobs

Beitrag von dr.e. » 19.03.2015, 19:52:31

Das verstehe ich nicht ganz. Ist

Code: Alles auswählen

use PHP\Mail;  
eine native PHP-Klasse? Falls nein, könnte doch dort der Fehler liegen. Entschuldige, adss ich hier nicht mehr helfen kann, ohne Zugriff auf die Umgebung ist das schlicht nicht möglich. Versuche mal den Cron einfach nur mit einem Skelet laufen zu lassen und füge dann nach und nach wieder die eigentliche Funktionalität hinzu. Dann siehst du ja, wo genau es kracht.
Viele Grüße,
Christian

Benutzeravatar
Paric
Beiträge: 45
Registriert: 25.08.2014, 08:51:04

Re: Cronjobs

Beitrag von Paric » 20.03.2015, 10:04:54

Hallo Christern,

danke das Du mit mir meine Verzweiflung teilst :D
Ich versuche das ganze mal zu erklären, vielleicht kommt dann ein bisschen Klarheit in die ganze Sache. Ich möchte in dem cronjob ein imap-E-Mail-Konto auf bestimmte Mails scannen. Es handelt sich dabei um Mails die bei uns über einen Fax-Server mit einem Service "Fax to Mail" generiert werden. Diesen Mails muss ich antworten, damit ein Antwortfax generiert wird.
Soweit zu der Funktion. Autark gibt es ein funktionierendes script:

Code: Alles auswählen

require_once "Mail.php";

$server = "server";
$userImap = "userImap";
$userSmtp = "userSmtp";
$passwort = "pw";
$host = "host";
$smtpHost = "SmtpHost";
$smtpPort = "465";
$searchString = "FAXG3/+4930...";
$betreff = "Testfax";
$textbereichDefault = "Das Testfax von der Fax-Nummer #faxnummer# war erfolgreich.";
$arrZuLoeschen = array(
                        "Zugestellt:",
                        "Unzustellbar:",
                        "Abwesenheitsnotiz"
);

if (!($mbox = imap_open($server, $userImap, $passwort))) {
    die();
}
$n_msgs = imap_num_msg($mbox);
for ($i=1; $i<=$n_msgs; $i++) {
    $header = imap_header($mbox, $i);
    $from = $header->from[0];
    if ($from->host == $host) {
        $faxnummer = str_replace($searchString, "", $from->mailbox);
        if (is_numeric($faxnummer) && strlen($faxnummer) == 5) {
            $empfaenger = $faxnummer . '@###.###;
            $headers = array ('From'    => "$userSmtp@###.de",
                              'To'      => $empfaenger,
                              'Subject' => $betreff);
            $smtp = Mail::factory('smtp',
                                   array (  'host'      => $smtpHost,
                                            'port'      => $smtpPort,
                                            'auth'      => true,
                                            'username'  => $userSmtp,
                                            'password'  => $passwort));
            $textbereich = str_replace("#faxnummer#", $faxnummer, $textbereichDefault);
            $mail = $smtp->send($empfaenger, $headers, $textbereich);
           if (PEAR::isError($mail)) {
               echo("<p>" . $mail->getMessage() . "</p>");
            } else {
                imap_delete($mbox, $i);
            }
        }
    } else {
        foreach($arrZuLoeschen as $loeschen) {
            if (strpos($header->subject, $loeschen) !== FALSE && $from->mailbox == $userSmtp) {
                imap_delete($mbox, $i);
            }
        }
    }
}
imap_expunge($mbox);
imap_close($mbox);
Da ich die Mail per smtp verschicken muss, habe ich mich der Klasse PEAR::Mail bediehnt, welche schon mit PHP mitgeliefert wird.

Was ich möchte ist, diese Klasse sauber in mein APF einladen lassen, und dann mich dieser Klasse zu bediehnen.

Ich habe eine Test-Klasse erstellt die nichts anderes macht, als auf die Funktion Mail::factory() zuzugreifen.

cron.php:

Code: Alles auswählen

$apfClassLoaderConfigurationRootPath = './TELLA';
include('/daten/httpd/tella/DEV/APF/core/bootstrap.php');

use APF\core\loader\RootClassLoader;
use APF\core\loader\StandardClassLoader;
use APF\core\singleton\Singleton;
use APF\core\registry\Registry;
use APF\core\configuration\ConfigurationManager;
use APF\tools\request\RequestHandler;

$classLoader = new StandardClassLoader('TELLA', 'TELLA');
$phpClassLoader = new StandardClassLoader('PHP', '/storage/disk3/lampp/lib/php');
RootClassLoader::addLoader($classLoader);
RootClassLoader::addLoader($phpClassLoader);

ConfigurationManager::retrieveProvider('ini')->setOmitContext(true);

$fC = Singleton::getInstance('APF\core\frontcontroller\Frontcontroller');

Registry::register('APF\core', 'Environment', 'DEFAULT');

$action = RequestHandler::getValue("action");

$fC->registerAction('TELLA\biz\actions', 'register-globals');
$fC->registerAction('TELLA\biz\actions', 'register-logs');
$fC->registerAction('TELLA\cron', $action . 'Crontab');
echo $fC->start('TELLA\pres\templates\init', 'dummy'); 
TestCrontabAction.php:

Code: Alles auswählen

namespace TELLA\crontabs;

use APF\core\frontcontroller\AbstractFrontcontrollerAction;

class TestCrontabAction extends AbstractFrontcontrollerAction
{
    public function __construct()
    {
        $this->type = self::TYPE_PRE_PAGE_CREATE;
    }
    
    public function run()
    {
        print "Test start<br>";
        $smtp = \PHP\Mail::factory('smtp',
                       array (  'host'      => "host",
                                'port'      => "port",
                                'auth'      => true,
                                'username'  => "name",
                                'password'  => "password"));
        print "Test erfolgreich";
    }
} 
und da scheitert es schon. ich bekomme keine Ausgabe, also das gleiche Ergebnis wie in meinem ersten Post.
Hoffe es scheint nun etwas klarer.

Beste Grüße,
Pit

Benutzeravatar
dr.e.
Administrator
Beiträge: 4536
Registriert: 04.11.2007, 16:13:53

Re: Cronjobs

Beitrag von dr.e. » 21.03.2015, 00:37:41

Hallo Pit,

nun sehe ich klarer, danke! :) Ich denke das erste was wir erreichen müssen ist eine Ausgabe zu erhalten. Kannst du mal wie oben vorgeschlagen versuchen PHP dazu zu bewegen etwas auszuspucken? Vermute weiterhin, dass da etwas mit dem Autoloading nicht hinhaut.
Viele Grüße,
Christian

Benutzeravatar
Paric
Beiträge: 45
Registriert: 25.08.2014, 08:51:04

Re: Cronjobs

Beitrag von Paric » 23.03.2015, 11:01:48

Moin Christian,

ich habe ein wenig rumprobiert...

1. Versuch, die Klasse in meiner Action zu includen:

Code: Alles auswählen

namespace TELLA\crontabs;

use APF\core\frontcontroller\AbstractFrontcontrollerAction;

class TestCrontabAction extends AbstractFrontcontrollerAction
{
    public function __construct()
    {
        $this->type = self::TYPE_PRE_PAGE_CREATE;
    }
    
    public function run()
    {
        print "Test start<br>";
        include("/storage/disk3/lampp/lib/php/Mail.php");
        $smtp = Mail::factory('smtp',
                       array (  'host'      => "host",
                                'port'      => "port",
                                'auth'      => true,
                                'username'  => "name",
                                'password'  => "password"));
        print "Test erfolgreich";
Ergebnis ist diese Fehlermeldung:

Code: Alles auswählen

Fatal error: Class 'APF\core\logging\entry\SimpleLogEntry' not found in /storage/disk3/lampp/lib/php/Mail.php on line 55
2. Versuch, diesen include noch VOR der bootstrap-Datei zu includen:

Code: Alles auswählen

include("/storage/disk3/lampp/lib/php/Mail.php");
$apfClassLoaderConfigurationRootPath = './TELLA';
include('/daten/httpd/tella/DEV/APF/core/bootstrap.php');

use APF\core\loader\RootClassLoader;
use APF\core\loader\StandardClassLoader;
use APF\core\singleton\Singleton;
use APF\core\registry\Registry;
use APF\core\configuration\ConfigurationManager;
use APF\tools\request\RequestHandler;

$classLoader = new StandardClassLoader('TELLA', 'TELLA');
 $phpClassLoader = new StandardClassLoader('PHP', '/storage/disk3/lampp/lib/php');
RootClassLoader::addLoader($classLoader);
 RootClassLoader::addLoader($phpClassLoader);

ConfigurationManager::retrieveProvider('ini')->setOmitContext(true);

$fC = Singleton::getInstance('APF\core\frontcontroller\Frontcontroller');

Registry::register('APF\core', 'Environment', 'DEFAULT');

$action = RequestHandler::getValue("action");

$fC->registerAction('TELLA\biz\actions', 'register-globals');
$fC->registerAction('TELLA\biz\actions', 'register-logs');
$fC->registerAction('TELLA\cron', $action . 'Crontab');
echo $fC->start('TELLA\pres\templates\init', 'dummy');
Fehlermeldung:

Code: Alles auswählen

Deprecated: Assigning the return value of new by reference is deprecated in /storage/disk3/lampp/lib/php/Mail.php on line 55

Deprecated: Assigning the return value of new by reference is deprecated in /storage/disk3/lampp/lib/php/Mail.php on line 135
Test start
Fatal error: Class 'TELLA\crontabs\Mail' not found in /daten/httpd/tella/DEV/TELLA/crontabs/TestCrontabAction.php on line 17
Also ich interpretiere es so, das es eine Depreced-Meldung seitens PHP gibt, die APF dazu veranlasst diesen in den Logger zu geben, was ihm aber misslingt, da er diesen in der Klasse Mail sucht.
Ich kann auch völlig falsch liegen, aber so sieht es für mich aus.

Achso, meine APF-Version ist die 2.1.1.

Beste Grüße,
Pit

Benutzeravatar
dr.e.
Administrator
Beiträge: 4536
Registriert: 04.11.2007, 16:13:53

Re: Cronjobs

Beitrag von dr.e. » 23.03.2015, 14:37:22

Hallo Pit,

danke für deine Analyse!
Deprecated: Assigning the return value of new by reference is deprecated in /storage/disk3/lampp/lib/php/Mail.php on line 55
Das ist in der Tat ein Problem der Mail-Klasse auf der genannten Zeile.
Fatal error: Class 'TELLA\crontabs\Mail' not found in /daten/httpd/tella/DEV/TELLA/crontabs/TestCrontabAction.php on line 17
Das bedeutet, dass die Klasse Mail ohne Namespace-Support daher kommt und daher von PHP unter dem Namespace der aktuellen Action gesucht wird. Der ClassLoader kann sie da natürlich nicht finden und deine Applikation geht Baden... :roll:
Fatal error: Class 'APF\core\logging\entry\SimpleLogEntry' not found in /storage/disk3/lampp/lib/php/Mail.php on line 55
Hier geht irgendwas beim Erzeugen eines Log-Eintrags schief. Mich wundert allerdings sehr, dass Mail.php den APF Logger nutzt. Hast du daran irgendwas modifiziert? Auf Zeile 55 steht bei mir der Kommentar
* @package Mail
Mein Vorschlag ist: poste mal Zeile 55 deiner Mail.php, vielleicht kommen wir dann einen Schritt weiter.
Viele Grüße,
Christian

Benutzeravatar
Paric
Beiträge: 45
Registriert: 25.08.2014, 08:51:04

Re: Cronjobs

Beitrag von Paric » 24.03.2015, 09:44:33

guten morgen Christian,

ich habe die Datei nicht modifiziert, doch meine PHP-Version auf dem Server ist nicht die neueste. Wir sind noch auf PHP 5.4.

die Zeile 55 besagt:

Code: Alles auswählen

            $mailer = &new $class($params); 
und die Funktion in der diese ist:

Code: Alles auswählen

    /**
     * Provides an interface for generating Mail:: objects of various
     * types
     *
     * @param string $driver The kind of Mail:: object to instantiate.
     * @param array  $params The parameters to pass to the Mail:: object.
     * @return object Mail a instance of the driver class or if fails a PEAR Error
     * @access public
     */
    function &factory($driver, $params = array())
    {
        $driver = strtolower($driver);
        @include_once 'Mail/' . $driver . '.php';
        $class = 'Mail_' . $driver;
        if (class_exists($class)) {
            $mailer = &new $class($params);
        } else {
            $mailer = PEAR::raiseError('Unable to find class for driver ' . $driver);
        }

        return $mailer;
    } 
allerdings scheint die Mail.php für PHP 4 geschrieben worden zu sein, wie der Kopf vermuten lässt:

Code: Alles auswählen

// +----------------------------------------------------------------------+
// | PHP Version 4                                                        |
// +----------------------------------------------------------------------+
// | Copyright (c) 1997-2003 The PHP Group                                |
// +----------------------------------------------------------------------+
// | This source file is subject to version 2.02 of the PHP license,      |
// | that is bundled with this package in the file LICENSE, and is        |
// | available at through the world-wide-web at                           |
// | http://www.php.net/license/2_02.txt.                                 |
// | If you did not receive a copy of the PHP license and are unable to   |
// | obtain it through the world-wide-web, please send a note to          |
// | license@php.net so we can mail you a copy immediately.               |
// +----------------------------------------------------------------------+
// | Author: Chuck Hagenbuch <chuck@horde.org>                            |
// +----------------------------------------------------------------------+
//
// $Id: Mail.php,v 1.11 2005/06/26 23:37:18 jon Exp $ 
das stimmt mich traurig :D

Benutzeravatar
dr.e.
Administrator
Beiträge: 4536
Registriert: 04.11.2007, 16:13:53

Re: Cronjobs

Beitrag von dr.e. » 25.03.2015, 17:47:57

Hi,

dann tiggert entweder

Code: Alles auswählen

$mailer = PEAR::raiseError('Unable to find class for driver ' . $driver); 
oder auch das "&" in

Code: Alles auswählen

$mailer = &new $class($params); 
den GlobalErrorHandler und damit den Logger. was du mal für die weitere Analyse machen kannst ist in der index.php ein

Code: Alles auswählen

GlobalErrorHandler::disable();
GlobalExceptionHandler::disable(); 
einzufügen. Vielleicht bekommst du dann noch mehr Informationen.
allerdings scheint die Mail.php für PHP 4 geschrieben worden zu sein, wie der Kopf vermuten lässt:
Falls das alles nix hilft, versuche mal die PEAR-Klasse einfach mit deinem Projekt direkt mitzuliefen und einfach eine "neuere" zu nutzen.
Viele Grüße,
Christian

Antworten

Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 1 Gast