CrAcKeR: Skriptabbruch

Hallo zusammen

Ich hab mir ein script gebaut, welches per file() ab ner HTML-Seite ein Log-File holt. Nun hab ich das Problem, dass wenn das Logfile über 20'000 Zeilen hat, das Script nach 30-40 Sekunden abstürzt. Der Internet Explorer zeigt ein "Seite konnte nicht geladen werden" an ... der FireFox meint garnix (leere Seite ohne Qullcode).

Weiss jemand, wie ich das beheben oder zumindest den Fehler einkreisen kann?

Danke im Voraus
CrAcKeR

  1. hallo,

    Weiss jemand, wie ich [...] den Fehler einkreisen kann?

    Ja: mehrfach drumherumlaufen.

    Alternativ könntest du unter Umständen auch den relevanten Code angeben. Oder dafür sorgen, daß dein log-File eben nicht größer wird, sondern, sofern es diese Größe erreicht, einfach ein neues angelegt wird.

    Grüße aus Berlin

    Christoph S.

    --
    Visitenkarte
    ss:| zu:) ls:& fo:) va:) sh:| rl:|
    1. Hallo CrAcKeR,

      Alternativ könntest du unter Umständen auch den relevanten Code angeben. Oder dafür sorgen, daß dein log-File eben nicht größer wird, sondern, sofern es diese Größe erreicht, einfach ein neues angelegt wird.

      Interessant zum Code wäre auch die genau Angabe der Serverversion und Auszug der Serverkonfiguration für die Direktiven RLimitMEM und RLimitCPU.
      In einigen Versionen (2.0.x) des Apachen wird bei Überschreitung der festgesetzten Grenzen die Verbinung kommentarlos geschlossen.

      Gruß aus Berlin!
      eddi

      1. Hallo CrAcKeR,

        Hallo XaraX

        Interessant zum Code wäre auch die genau Angabe der Serverversion

        Apache/2.0.54 (Unix) mod_ssl/2.0.54 OpenSSL/0.9.7g PHP/5.0.4 DAV/2 mod_perl/1.999.21 Perl/v5.8.6
        PHP Version 5.0.4

        und Auszug der Serverkonfiguration für die Direktiven RLimitMEM und RLimitCPU.

        Die müssten ja in der httpd.conf oder in der apache2.conf sein ...
        steht aber in beiden keiner dieser beiden Befehle drinnen ...

        In einigen Versionen (2.0.x) des Apachen wird bei Überschreitung der festgesetzten Grenzen die Verbinung kommentarlos geschlossen.

        Das durfte ich auch feststellen :((

        Gruß aus Berlin!

        Gruss aus der Schweiz
        CrAcKeR

    2. hallo,

      hallo

      Weiss jemand, wie ich [...] den Fehler einkreisen kann?
      Ja: mehrfach drumherumlaufen.

      haha ... witz komm raus du bist umzingelt *g*

      Alternativ könntest du unter Umständen auch den relevanten Code angeben.

      em ... das kann ich schon ... is nur relativ viel ;)
      $r = new HTTPRequest("http://".$_POST["host"]."/logs.php?session=".$sess."&such=".$admin);
      $ary = $r->DownloadToArry();

      Dies wird bis zu 5 mal (mit unterschiedlichen parametern) ausgeführt. die Klasse HTTPRequest sieht dann so aus:
      class HTTPRequest
      {
         var $_fp;        // HTTP socket
         var $_url;        // full URL
         var $_host;        // HTTP host
         var $_protocol;    // protocol (HTTP/HTTPS)
         var $_uri;        // request URI
         var $_port;        // port

      // scan url
         function _scan_url(){
             $req = $this->_url;
             $pos = strpos($req, '://');
             $this->_protocol = strtolower(substr($req, 0, $pos));
             $req = substr($req, $pos+3);
             $pos = strpos($req, '/');
             if($pos === false) $pos = strlen($req);
             $host = substr($req, 0, $pos);
             if(strpos($host, ':') !== false) list($this->_host, $this->_port) = explode(':', $host);
             else{
                 $this->_host = $host;
                 $this->_port = ($this->_protocol == 'https') ? 443 : 80;
             }
             $this->_uri = substr($req, $pos);
             if($this->_uri == '') $this->_uri = '/';
         }

      // constructor
         function HTTPRequest($url){
             $this->_url = $url;
             $this->_scan_url();
         }

      function DownloadToArry(){
             $crlf = "\r\n";
             // generate request
             $req = 'GET ' . $this->_uri . ' HTTP/1.0' . $crlf . 'Host: ' . $this->_host . $crlf . $crlf;
             // fetch
             $this->_fp = fsockopen(($this->_protocol == 'https' ? 'ssl://' : '') . $this->_host, $this->_port);
             fwrite($this->_fp, $req);
             while(is_resource($this->_fp) && $this->_fp && !feof($this->_fp)) $response .= fread($this->_fp, 1024);
             fclose($this->_fp);
             // split header and body
             $pos = strpos($response, $crlf . $crlf);
             if($pos === false) return($response);
             $header = substr($response, 0, $pos);
             $body = substr($response, $pos + 2 * strlen($crlf));
             // parse headers
             $headers = array();
             $lines = explode($crlf, $header);
             foreach($lines as $line)
                 if(($pos = strpos($line, ':')) !== false)
                     $headers[strtolower(trim(substr($line, 0, $pos)))] = trim(substr($line, $pos+1));
             return explode("\n",$body);
         }
      }

      Oder dafür sorgen, daß dein log-File eben nicht größer wird, sondern, sofern es diese Größe erreicht, einfach ein neues angelegt wird.

      Geht leider nicht, da ich weder einfluss noch schreibrechte auf das File hab.

      Grüße aus Berlin

      Grüsse aus der Schweiz ;)
      CrAcKeR

      1. Hallo CeAcKeR,

        die Klasse ist ansich bei einer Version 5.0.4 PHPs "Schnee von Gestern": http://de3.php.net/manual/de/function.stream-context-create.php

        Viel wichtiger wäre in Erfahrung zu bringen, ob der Webserver überhaut einen Response senden oder, (wie vermutet) die Verbindung einfacht kappt. Dazu würde ich Dich bitten dies entweder mit einem kleinen Script, daß eine HTTP-Auswertung vornimmt, selbst zu testen, oder den Link hier zu posten, um die Header auslesen zu können.

        Gruß aus Berlin!
        eddi

        1. Hallo CeAcKeR,

          Hallo XaraX

          die Klasse ist ansich bei einer Version 5.0.4 PHPs "Schnee von Gestern":

          Danke für den Link .. bringt vieleicht auch nochma was ;)

          Viel wichtiger wäre in Erfahrung zu bringen, ob der Webserver überhaut einen Response senden oder, (wie vermutet) die Verbindung einfacht kappt. Dazu würde ich Dich bitten dies entweder mit einem kleinen Script, daß eine HTTP-Auswertung vornimmt, selbst zu testen, oder den Link hier zu posten, um die Header auslesen zu können.

          Link posten geht leider nicht, da es sich hier um geschützte Bereiche handelt. Sorry.
          Nen kollege von mir hat das ganze mal von seinem Rechner aus laufen gelassen und folgenden Fehler erhalten:

          Fatal error: Allowed memory size of 8388608 bytes exhausted (tried to allocate 2021029 bytes) in /path-to-script.php on line 123

          Auf Zeile 123 steht folgendes:
          for($j = 0; $j < count($ary); $j++) if(stristr($ary[$j],"<h3>Logs</h3>")) $tmp = $ary[$j];

          $ary[] ist das array, welches mit der Klasse eingelesen wird.

          Gruss CrAcKeR

          1. Moin CrAcKeR,

            Fatal error: Allowed memory size of 8388608 bytes exhausted (tried to allocate 2021029 bytes) in /path-to-script.php on line 123

            es liegt also ein Überschreiten des Limits für zu verbrauchenden Speicher vor. Meine Empfehlung:

            - mittels ini_set('memory_limit','100M'); den erlaubten Speicherverbrauch heraufsetzen
             - mittels memory_get_usage(); den tatsächlichen Verbrauch ermitteln
             - und die Konfiguration des Servers (httpd.conf|php.ini) bedarfsorientiert verändern

            Gruß aus Berlin!
            eddi

            1. Moin CrAcKeR,

              Moin eddi

              • mittels ini_set('memory_limit','100M'); den erlaubten Speicherverbrauch heraufsetzen
              • mittels memory_get_usage(); den tatsächlichen Verbrauch ermitteln
              • und die Konfiguration des Servers (httpd.conf|php.ini) bedarfsorientiert verändern

              Danke dir ... Funzt super ;) hab's nun mal auf 10MB gesetzt ;)
              Die rückgabe ergab 599KB ... was dann das überlaufen bewirkt hatte.

              Die conf-files werd ich jedoch ned anpassen, da es sich nur um ein script handelt, das solche mengen herumschaufelt ... bei den andern mach ich kleinere Log-Häppchen, wo das möglich ist.

              Danke nochmal und nen schönen Abend
              CrAcKeR

            2. Hallo,

              es sollte aber primär das Ziel sein, den Speicherbefarf zu kontollieren und zu vermindern.

              Das kann man z.B. durch rechtzeitige Freigabe von Variablen. Außerdem sollte man auch darauf achten, dass keine verlorenen Handles erzeugt werden.

              LG
              Chris

              1. Hallo Chris,

                es sollte aber primär das Ziel sein, den Speicherbefarf zu kontollieren und zu vermindern.
                Das kann man z.B. durch rechtzeitige Freigabe von Variablen.

                im vorliegenden Beispiel ist dies wohl eher schwer möglich. Anderfalls lasse ich mich durch ein Scriptbeispiel gerne vom Gegenteil überzeugen ;)

                Gruß aus Berlin!
                eddi

                1. im vorliegenden Beispiel ist dies wohl eher schwer möglich. Anderfalls lasse ich mich durch ein Scriptbeispiel gerne vom Gegenteil überzeugen ;)

                  Würd ich auch meinen, da es sich um reichlich Daten handelt, die eingelesen werden ;) Es sind 10k-40k Zeilen a ja ca 100 Zeichen ;)

                  Gruss CrAcKeR

                  1. Chris

                    im vorliegenden Beispiel ist dies wohl eher schwer möglich. Anderfalls lasse ich mich durch ein Scriptbeispiel gerne vom Gegenteil überzeugen ;)

                    Würd ich auch meinen, da es sich um reichlich Daten handelt, die eingelesen werden ;) Es sind 10k-40k Zeilen a ja ca 100 Zeichen ;)

                    Und wieso müssen die im Arbeitsspeicher gehalten werden?

                    Da lob ich mir doch die guten alten Assembler-Leute. Die wussten noch, was sie taten.

                    LG
                    Chris

                    1. Hallo Chris,

                      Und wieso müssen die im Arbeitsspeicher gehalten werden?

                      Wo sollen sie sonst gehalten werden? Auf der Festplatte? Wo wäre dort Deiner Meinung nach der Vorteil?

                      Gruß aus Berlin!
                      eddi

  2. Hallo,

    PHP begrenzt die Auswertezeit einzeler Scripte mit der Einstellung
    max_execution_time
    http://de3.php.net/manual/en/ref.info.php#ini.max-execution-time
    siehe auch http://de3.php.net/manual/en/ini.php#ini.list

    Die kannst Du ggf. am Scriptanfang setzen mit
    http://de3.php.net/manual/en/function.set-time-limit.php,
    aber nur dann, wenn der Server nicht im Safe Mode läuft.
    Musst Du Dir mal mit http://de3.php.net/manual/en/function.phpinfo.php
    die Einstellungen ansehen.

    Außerdem kannst Du Dein Script wahrscheinlich noch erheblich beschleunigen.

    Nur mal so zum Test:

    <?php

    function microtime_float()
         {
           list($usec, $sec) = explode(" ", microtime());
           return ((float)$usec + (float)$sec);
         }
       ---------------------------------------------------
         $start = microtime_float();

    $trash = file(<dateiname>);

    $stop = microtime_float();

    echo "Ladezeit: ".($stop-$start);

    ?>

    Der zeitaufwändigste Teil an Deinem Script wird vermutlich die Ausgabe sein. Du solltest vermeiden, jede generierte Zeile dirket mit echo auszugeben, sondern auch die Ausgabe erst in einer Variablen sammeln, die dann in einem Stück ausgegeben wird.

    Versuch da mal, die verschiedenen Varianten auszumessen.
    Rückmeldung wird erbeten :-)

    LG
    Chris

    1. Hallo,

      Huhu

      max-execution-time

      Steht auf 60, Script wird aber nach 30 Sekunden abgebrochen

      set-time-limit

      Steht auf null (unbegrenzt)

      aber nur dann, wenn der Server nicht im Safe Mode läuft.

      Tut er nicht

      Musst Du Dir mal mit phpinfo die Einstellungen ansehen.

      Hab ich, die Werte passen, so wie ich die eingestellt hab.

      Außerdem kannst Du Dein Script wahrscheinlich noch erheblich beschleunigen.

      Hm ... das is ne gute Frage ... aber wie *g*

      Nur mal so zum Test:
      ...

      Geht nicht, da am ende ja die Verbindung gekappt wird.

      Der zeitaufwändigste Teil an Deinem Script wird vermutlich die Ausgabe sein...

      Nein ... ausgegeben werden zuletzt nur etwa 5 Zeilen (Statistik)

      Gruss CrAcKeR

  3. Hallo CrAcKeR,

    Hallo zusammen

    Ich hab mir ein script gebaut, welches per file() ab ner HTML-Seite ein Log-File holt. Nun hab ich das Problem, dass wenn das Logfile über 20'000 Zeilen hat, das Script nach 30-40 Sekunden abstürzt. Der Internet Explorer zeigt ein "Seite konnte nicht geladen werden" an ... der FireFox meint garnix (leere Seite ohne Qullcode).

    Weiss jemand, wie ich das beheben oder zumindest den Fehler einkreisen kann?

    set_time_limit(0);

    http://de.php.net/manual/de/function.set-time-limit.php

    MffG
    EisFuX

    --
    Erinnert mich ein Bisschen an die if-then-Schleifen von Java.
    (Alexandra Freund, IT-Compactkurs)
    1. set_time_limit(0);

      Funktioniert leider nicht ... genau der gleiche Effekt

      1. Hallo CrAcKeR,

        set_time_limit(0);
        Funktioniert leider nicht ... genau der gleiche Effekt

        Gut, jetzt ist geklärt, dass es sich nicht um die Begrenzung der
        Ausführungszeit des Scripts handelte sondern um Speichermangel. Das
        hättest du sicher eher bemerkt, wenn du die entsprechende Fehlermeldung
        auch gesehen hättest. Daher würde ich dir empfehlen, an den Anfang deiner
        Scripts immer folgenden Code zu setzen:

          
        error_reporting(E_ALL | E_STRICT);  
        @ini_set('display_errors', TRUE);  
        @ini_set('html_errors', TRUE);  
        
        

        Das gilt für PHP5. Für PHP4 solltest du das "| E_STRICT" weglassen.
        Auf diese Weise werden dir die Fehlermeldungen vom PHP-Interpreter
        auch im Webbrowser angezeigt.

        Das Zeug sollte natürlich nur dann da stehen, wenn das Script entwickelt
        und getestet wird.

        MffG
        EisFuX

        --
        Erinnert mich ein Bisschen an die if-then-Schleifen von Java.
        (Alexandra Freund, IT-Compactkurs)