Counter terminiert regelmässig
dey
- php
Hallo,
wir beutzen eine auf PHP-basis der aus 2 Dateien besteht:
1. Zähler hoch setzen
<?php
$data = file("count.dat");
$text = $data[0];
$text = $text + 1;
$openfile = fopen("count.dat", 'w+');
flock($openfile, 2);
fwrite($openfile, $text);
fclose($openfile);
?>
2. Weiterleitung auf Ausgabe
<script type="text/javascript">
<!--
location.replace('counter.php')
//-->
</script>
3. Ausgabe
$data = file("count.dat");
$text = $data[0];
$lentext = strlen($text);
for ($i = 1; $i <= $lentext; $i++)
{
$num = substr($text, $i-1, 1);
echo "<img src='../img/" . $num . ".gif' border='0' alt='no'>";
}
(Un-)regelmässig setzt sich der counter auf Null zurück. Vielleicht Count.dat gelöscht.
1. Wie kann ich den Grund dafür rausfinden?
2. Ist irgendwas in meinem Code dafür prädestiniert?
bydey
echo $begrüßung;
(Un-)regelmässig setzt sich der counter auf Null zurück. Vielleicht Count.dat gelöscht.
- Wie kann ich den Grund dafür rausfinden?
Du könntest ein Error-Logfile führen. Teste vor Zugriff auf die Datei, ob sie vorhanden ist und schreibe eine entsprechende Meldung in eine Datei.
- Ist irgendwas in meinem Code dafür prädestiniert?
Ja, es gibt mindestens eine Schwachstelle
$data = file("count.dat");
Wenn bei file() ein Fehler auftritt, wird kein Array sondern false zurückgeliefert. Diesen Sonderfall berücksichtigst du nicht. Vermutlich tritt dieser Fall auf, wenn die Datei gerade mit flock() gesperrt ist.
$text = $data[0];
false hat kein Element 0. Die entsprechende Notice wirst du sicherlich ignorieren, weil das die Default-Einstellung für das error_reporting ist. Hier hilft nur, Fehler, die im unbeaufsichtigtem Betrieb auftreten zu loggen. Dazu könnte man error_reporting auf E_ALL, display_errors auf 0, log_errors auf 1 und error_log auf einen Dateinamen setzen. Diese Datei sollte man dann regelmäßig kontrollieren.
$text = $text + 1;
Hier schlägt dann die automatische Typumwandlung von PHP zu. $data[0] hat NULL ergeben, das wird, weil damit gerechnet werden soll, in 0 umgewandelt und dann dein 1 addiert. ($x = $x + 1; kann man übrigens auch als $x++; schreiben.)
echo "$verabschiedung $name";
Hallo,
Wenn bei file() ein Fehler auftritt, wird kein Array sondern false zurückgeliefert. Diesen Sonderfall berücksichtigst du nicht. Vermutlich tritt dieser Fall auf, wenn die Datei gerade mit flock() gesperrt ist.
Nein!
Die flock()-Funktion ist nur advisory und muss daher in der Applikation beachtet werden. File() tut dies aber nicht.
Das bedeutet also, dass File() immer das ausliest, was gerade
noch vorhanden und lesbar ist.
Anders wäre das mit den dio_-Funktionen
http://de.php.net/manual/de/ref.dio.php
Die sperren die Datei in der Betriebssystemschicht, also mandatory.
Die Applikationen kommen also an dieser Sperre nicht vorbei.
Das würde dann auch für file() zutreffen.
Da File() aber eine namensbasierte Funktion ist und keine handlebasierte, eignet es sich nicht für Multiuser-Aufgaben, bzw. für
Datenmanipulation. File() sollte man ausschließlich für reine Datenanzeigen verwenden, bei denen die Konsistenz nicht wesentlich ist.
LG
Chris
Hallo,
Anders wäre das mit den dio_-Funktionen
http://de.php.net/manual/de/ref.dio.php
Die sperren die Datei in der Betriebssystemschicht, also mandatory.
Die Applikationen kommen also an dieser Sperre nicht vorbei.
Das würde dann auch für file() zutreffen.
leider wurden die DIO-Funktionen mit der Version 5.x aus den Standardmodulen herausgenommen und sind als PECL-Erweiterung erhältlich.
Weiß jemand, was sich die PHP-Entwickler dabei gedacht haben?
Gruß aus Berlin!
eddi
echo $begrüßung;
Die flock()-Funktion ist nur advisory
Jetzt, wo du es sagst, fällt es mir wieder ein, dass da ja sowas war. Allerdings fällt mir auch ein, dass es Unterschiede zwischen Windows und Unix gibt. Unter Windows ist flock mandatory. Dies weiß auch die Handbuchseite zu berichten:
flock -- Portable advisory file locking
...
Note: flock() is mandatory under Windows.
Meine Vermutung äußerte ich auch aufgrund eines Userkommentars (John 21-Jul-2003 01:32) auf der Handbuchseite zu file(). Leider schrieb er nicht, ob er Windows oder Unix verwendet hat.
Die flock()-Vermutung ziehe ich hiermit zurück. Den Rest lasse ich aber so stehen.
echo "$verabschiedung $name";
Hallo Dedlfix,
Die flock()-Funktion ist nur advisory
Jetzt, wo du es sagst, fällt es mir wieder ein, dass da ja sowas war. Allerdings fällt mir auch ein, dass es Unterschiede zwischen Windows und Unix gibt. Unter Windows ist flock mandatory. Dies weiß auch die Handbuchseite zu berichten:
flock -- Portable advisory file locking
...
Note: flock() is mandatory under Windows.Meine Vermutung äußerte ich auch aufgrund eines Userkommentars (John 21-Jul-2003 01:32) auf der Handbuchseite zu file(). Leider schrieb er nicht, ob er Windows oder Unix verwendet hat.
Die flock()-Vermutung ziehe ich hiermit zurück. Den Rest lasse ich aber so stehen.
Guter Hinweis. Den muss ich gleich weiterreichen.
Wird meinen Partner allerdings überhaupt nicht freuen. Der hat gerade vorgestern den Feature-Artikel übers Locking wieder aufgegriffen.
Die PHPler scheinen hier eine Menge Konfusion eingebaut zu haben. Wird ma wohl nicht drum herum kommen, in den Quellcode zu schauen, wenn alles stimmen soll später.
LG
Chris
Hallo,
wir beutzen eine auf PHP-basis der aus 2 Dateien besteht:
Könntest Du den Satz bitte mal ins Deutsche übersetzen? :-)
$openfile = fopen("count.dat", 'w+');
flock($openfile, 2);
fwrite($openfile, $text);
fclose($openfile);
Was soll das Filelocking hier noch bewirken?
Es ist bei PHP per default "advisory", also nur beratend.
Es hindert also nicht die funktion file(), das hier gerade
neu angelegte und noch leere File auszulesen.
File() ist ohnehin ungeeignet, um in einer Multiuser-Umgebung benutzt zu werden, wenn die ausgelesenen Daten konsistent bleiben müssen. Alle Krücken, die man zum "Sperren" um File() herumbauen könnte, helfen auch nicht wirklich weiter.
Nutze also die normalen fopen(), fread() und fwrite()
Um die Datei anzulegen, musst Du das entweder generell bei der Installation des Zählers tun und Dich nachher darauf verlassen können, dass es auch geklappt hat, oder aber Du musst es zerstörungsfrei machen.
Dazu benutzt man entweder
$fh = @fopen($dateiname,'+xb');
if ($fh !== false)
{
# hat geklappt, weitermachen
}
else
{
# Auswerten von $phperrmsg
# dazu muss track_errors = on sein!
}
Mit diesem Handle kann dann sofort weitergearbeitet werden
oder aber einfach
$fh = fopen($dateiname,'ab');
fclose($fh);
$fh = fopen($dateiname,'rb+');
und nun _erst_ locken,
dann auslesen
dann erhöhen
dann zurückspulen
dann schreiben
dann Dateilänge absitmmen (ftruncate())
dann Datei schließen
Durch das Schließen wird sie automatisch entsperrt.
Ich hoffe, dass Du alles verstanden hast.
LG
Chris
Hallo,
Ich hoffe, dass Du alles verstanden hast.
Im grossen und ganzen ja. Altes script - irgendwann mal kopiert als ich von php noch keine Ahnung hatte und nie wieder darüber nachgedacht.
bydey
Hallo,
Ich hoffe, dass Du alles verstanden hast.
Im grossen und ganzen ja. Altes script - irgendwann mal kopiert als ich von php noch keine Ahnung hatte und nie wieder darüber nachgedacht.
Viel spannender ist Deine noch fehlende Aussage, ob nun alles funktioniert...
LG
Chris
Hallo,
Viel spannender ist Deine noch fehlende Aussage, ob nun alles funktioniert...
Wäre schwierig festzustellen, da
a) der Fehler zufällig alle paar Monate auftritt und
b) es ja nicht sicher ist, dass wir auf der richtigen Fährte sind
und somit der Fehler nicht reproduzierbar ist.
Was bisher geschrieben wurde macht Sinn und ich werde es umsetzten.
bydey
Hallo,
Viel spannender ist Deine noch fehlende Aussage, ob nun alles funktioniert...
Wäre schwierig festzustellen, da
a) der Fehler zufällig alle paar Monate auftritt und
Das kann man mittels Multirequest mit dem Programm 'ab' eines Apache-Webservers sehr schnell herausfinden. meistens reichen schon wenige parallere Requests, um solche Fehler zu provozieren.
b) es ja nicht sicher ist, dass wir auf der richtigen Fährte sind
und somit der Fehler nicht reproduzierbar ist.
Auf der richtigen Fährte bist Du mit den Hinweisen auf jeden Fall.
Das wurde hier schließlich auch schon oft genug beschrieben!
Was bisher geschrieben wurde macht Sinn und ich werde es umsetzten.
Gut so. Und hinterher bitte Erfolgsbericht :-)
LG
Chris