Skriptabbruch
CrAcKeR
- php
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
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.
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
set_time_limit(0);
Funktioniert leider nicht ... genau der gleiche Effekt
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