Jirou: PHP Skript stoppen und weiterführen

Hallo,

ich habe ein Skript, das sehr lange läuft und dabei auch manchmal (intern)abgebrochen werden muss. Dieses Skript wird automatisch über einen Server ausgeführt.
Ich würde gerne den Zustand des Skriptes speichern/anhalten, sobald ein Problem auftritt(also kein php oder mysql error) und es dann nachdem ein anderes skript manuel ausgeführt wurde an der stelle mit diesen zustand weiter laufen lassen, indem ich ihn manuel sage es soll weiter laufen.

Ich glaube das wird nicht so ohne weiteres mölich seien, aber kennt jemand einen Trick, damit soetwas in der Art realisierbar ist?

Hoffe es war einigermaße verständlich.

  1. Hello,

    ich habe ein Skript, das sehr lange läuft und dabei auch manchmal (intern)abgebrochen werden muss. Dieses Skript wird automatisch über einen Server ausgeführt.
    Ich würde gerne den Zustand des Skriptes speichern/anhalten, sobald ein Problem auftritt(also kein php oder mysql error) und es dann nachdem ein anderes skript manuel ausgeführt wurde an der stelle mit diesen zustand weiter laufen lassen, indem ich ihn manuel sage es soll weiter laufen.

    Ich glaube das wird nicht so ohne weiteres mölich seien, aber kennt jemand einen Trick, damit soetwas in der Art realisierbar ist?

    Solange das Script durch den in PHP eingebauten Mechanismus abgebrochen wird, hilft Dir

    register_shutdown_function()
        http://de.php.net/manual/en/function.register-shutdown-function.php

    Das entspricht in etwa der Exit-Prozedur in Executables...

    Liebe Grüße aus dem schönen Oberharz

    Tom vom Berg

    --
     ☻_
    /▌
    / \ Nur selber lernen macht schlau
    http://bergpost.annerschbarrich.de
    1. Soweit ich weiß bricht es das Skript nur ab, oder?
      Also das könnte ich doch auch gleich durch exit oder die machen, aber es soll so ungefähr laufen

      //IrIrgendeine ausgabe oder einfach ein paar werte, die normalweise durch ein skript definiert werden
      echo "abc";
      $var = false;

      if($var != true) {
      //Skript anhalten
      }

      echo "Programm fertig";

      Jetzt soll das Skript an der stelle wo es anhalten musste, durch z.B. einen manuelen befehl, weiter laufen und die selben werte und parameter besitzten und die informationen die nötig waren um den oberen teil des skriptes auszuführen und genau nach den stopp weiter arbeiten.

      Geht sowas damit? Wenn ja gibs nen Ansatz? Wenn nein gibs ne alternative?

      1. Hello,

        Soweit ich weiß bricht es das Skript nur ab, oder?

        _Was_ bricht das Script nur ab?

        Mit register_shutdown_function() kannst Du eine bevorzugte Prozedur amelden, die vorher deklariert und definiert werden muss (das geschieht ja bei klassischem PHP i.d.R. in einem Schritt), die dann noch ausgeführt wird, wenn das Script endet oder zwangsweise abgebrochen wird.

        Liebe Grüße aus dem schönen Oberharz

        Tom vom Berg

        --
         ☻_
        /▌
        / \ Nur selber lernen macht schlau
        http://bergpost.annerschbarrich.de
        1. Also dann würde das ganze aber so aussehen

          function stop_script() {
            while(file_exists("stop.txt")) {
              sleep(5);
            }
            //Weiter laufen nur wie????
          }

          //HIER STEHT CODE

          $blah
          file_put_contents("stop.txt", $blah);
          register_shutdown_function(stop_script());
          die();

          Jetzt würde die Funktion stop_script solange laufen bis die datei stop.txt gelöscht wurde durch z.B. ein zweites Skript.

          Wie sag ich den Skript jetzt, dass es dann nach dem Stop weiter machen soll?

          Also hab das Skript jetzt nicht getestet aber sollte verständlich sein was gemint ist. Aber mich würde auch interessieren ob man das etwas weniger server lastig machen kann, wenn das skript pausenlos läuft bis man selber reagiert ist das nicht sooo super...

          1. Hello,

            Also dann würde das ganze aber so aussehen

            <?php   ### start_endlos_script.php ### per Browser starten

            set_time_limit(0);     ## http://de.php.net/manual/en/function.set-time-limit.php
                ignore_user_abort(1);  ## http://de.php.net/manual/en/function.ignore-user-abort.php
                touch ('stop.txt');

            $filename = 'control_file.txt';
                register_shutdown_function('exit_function');

            static $counter = 0;

            #-----------------------

            function do_something($filename, $data)
                {
                    file_put_contents($filename, $data . "\r\n", FILE_APPEND);
                }
            #-----------------------

            function run_script($filename, $data)
                {
                    while(file_exists("stop.txt"))
                    {
                        do_something($filename, $data);
                        sleep(5);
                    }
                }
            #-----------------------

            function exit_function()
                {
                    ## write all status data to file
                }
            #=======================

            run_script($filename, $counter++ . ' es ist jetzt ' . date('Y-m-d H:i_s'));

            ?>

            Probier es mal so.
            Noch ungeprüft.
            Es gibt aber genügend Threads hier im Archiv, wenn Du nach "Dauerlauf" suchst

            Liebe Grüße aus dem schönen Oberharz

            Tom vom Berg

            --
             ☻_
            /▌
            / \ Nur selber lernen macht schlau
            http://bergpost.annerschbarrich.de
            1. Danke das du dir die Mühe gemacht hast, aber es ist nicht ganz so wie ich es wollte, aber es hat mit trozdem etwas geholfen, da ich dieses Endlos Skript auch brauchen kann.

              Also nochmal, hoffe es ist verständlicher:

              Ich habe ein Skript A, das irgendetwas bearbeitet. Dabei kann und wird es zu unvorhersebaren "Problemen" kommen. Dies passiert indem etwas den Skirpt z.B. nicht passt(eine Bedinung nicht mehr erfüllt ist). Deshalb wird dieses Skript gestoppt, wobei es wichtig ist, dass es in genau diesen Zustand erhalten bleibt um es später durch Skript B wieder zu laufen zu bringen.

              Mit Zustand meine ich z.B. das Funktion A einen Parameter bekam und dann dadurch eine Funktion B auffruft, die wiederrum plötzlich eine Unstimmigkeit("Problem") hat und deshalb das Skript stoppen muss. Dieser Zustand muss erhalten sein, dass Funktion B an der "Stoppstelle" weiter arbeiten und dann die weiteren Befehlen von Funktion A ausführt.

              Jetzt soll ein Skript B diese Unstimmigkeit("Problem") lösen, indem sie z.B. eine Datei löscht/erstellt oder einen Mysql Eintrag macht(tut aber nicht zur Sache, da es ne einfache Bedingung in Skript A ist).

              Jetzt soll wie eben schon gesagt Skript A an der "Stoppstelle" weiter arbeiten.

              Meine eigentliche Frage war jetzt, ob es möglich ist, den Zustand des Skriptes und den Fortschritt des abarbeitens(parsen) so zu stoppen, dass Skript A nicht endlos weiter läuft bis die Bedingung, die durch Skript B ausgelöst wird erfüllt ist.
              Der Grund wäre z.B. eine höhere Auslastung oder ein unvorhergesehener/geplanter Neustart des Servers.

              1. -1. Schreibe ein sinnvoll* aufgebautes script A und starte es.
                0. Problem
                1. Speichere alle zum Fortfahren notwendigen Informationen in einer Datenbank oder in einer Datei und stoppe das script.
                2. Führe script B aus und starte vor oder mit dem Beenden script A.

                * bei dem das Fortfahren möglich ist ohne fürchterliche Eventualitäten berücksichtigen zu müssen

              2. Hi!

                Ich habe ein Skript A, das irgendetwas bearbeitet.

                Beschäftige dich mal mit PHP-CLI, da sollte dein Vorhaben besser steuerbar/überwachbar sein.

                do {

                // alles mögliche

                // wirf fehler
                  var_dump($was_koennte_es_sein);

                // arbeite aufgaben ab

                // prüfe, ob datensätze verändert/ergänzt/gelöscht wurde

                // reagiere darauf :D

                // wenn alles erledigt
                  exit(0);

                // schongang
                  usleep(1000);

                } while(true)

                Hat natürlich auch den Vorteil, daß es ewig laufen kann (wenn man das möchte).

                lG,
                Jonny 5

      2. Hi,

        [...] es soll so ungefähr laufen

        //IrIrgendeine ausgabe oder einfach ein paar werte, die normalweise durch ein skript definiert werden
        echo "abc";
        $var = false;

        if($var != true) {
        //Skript anhalten
        }

        Das kann so natürlich nicht funktionieren, weil keine andere Scriptinstanz den Wert von $var verändern kann.

        Du bräuchtest also etwas „ausserhalb” des Scriptes liegendes, auf das auch andere Scripte Zugriff haben, an hand dessen du die Entscheidung treffen kannst. Das könnte bspw. die Existenz einer Datei mit einem bestimmten Namen* oder ein Datenbankeintrag sein (beides nicht sonderlich performant); oder auch ein entsprechendes Flag in einem gemeinsam genutzten Speicherbereich (Stichwort SHMOP).

        * würde noch zusätzlich clearstatcache im prüfenden Script erfordern, damit es davon auch etwas mitbekommt.

        MfG ChrisB

        --
        “Whoever best describes the problem is the person most likely to solve the problem.” [Dan Roam]
      3. Hello,

        if($var != true) {
        //Skript anhalten
        }

        Wenn es Dir darum geht, ein Script per Browser zu starten, dann in den Hintergrund zu stellen und den Browser schließen zu können, ohne dass das Script davon betroffen ist, so ist das möglich.

        PHP benötigt dazu die Möglichkeit, eine Instanz z.B. mit Exec() aufrufen und abspalten zu können. Dies ist prinzipiell möglich, aber nicht auf jedem Host (nicht bei jedem Hoster).

        Beispiele dazu, wie sowas geht, findest Du in den UCN (User contributed Notes) der Funktion exec()

        http://de.php.net/manual/en/function.exec.php

        Man nehme ein Script 'dauerlauf.php', dass keine Ausgabe auf die Standardausgabe macht und eine Endlosschleife enthält und starte es mit:

        <?php

        $pid = exec("/usr/local/bin/php dauerlauf.php > /dev/null & echo $!");

        echo "<p>Script inter PID $pid gestartet</p>\n";

        ?>

        Dazu muss im Pfad

        /usr/local/bin/php

        der PHP-Interpreter liegen und für den PHP-Prozess, der das obige Script aufruft, ausführbar sein.

        Liebe Grüße aus dem schönen Oberharz

        Tom vom Berg

        --
         ☻_
        /▌
        / \ Nur selber lernen macht schlau
        http://bergpost.annerschbarrich.de
        1. Nein ich will lediglich ein Skript automatisch im Hintergrund ausführen(das ist kein Problem und nicht die Frage), dass bei einen bestimmten Punkt anhalten soll und wartet, bis jemand seinen Browser aufmacht und zb. einen mysql eintrag verursacht, der wiederrum das andere Skript zum weiterlaufen bewegt. Das beste wäre natürlich, wenn das 1. Skript beim Anhalten überhaupt kein Traffic verursacht in den man den Zustand/Fortschritt des Skriptes abspeichert um damit dann an der Stelle weiter zu arbeiten.