PHP-Verhaltensweisen unter verschiedenen OS
Tom
- php
Hello,
ich benötige nochmals Eure Hilfe.
Was steht auf Euren Systemen in
$_SERVER['SERVER_SOFTWARE'] Apache/1.3.27 (Unix) PHP/4.3.1
Und welches OS betreibt Ihr?
Dann nochmals eine Bitte an die Windows-User:
Was passiert bei Euch mit dem Buffer, wenn man schon einige Ausgaben gemacht hat und dann erst ob_start() auslöst, dann wiedr einige Ausgaben macht und dann wieder ob_start() auslöst?
<?php ### buffercheck_obstart.php ###
echo str_repeat('A ', 100);
echo "<hr>";
sleep(5);
ob_start();
echo str_repeat('B ', 100);
echo "<hr>";
sleep(5);
ob_start();
echo str_repeat('C ', 100);
echo "<hr>";
sleep(5);
ob_start();
ob_end_flush();
?>
oder mit
<?php ### buffercheck_implicit.php ###
ob_implicit_flush();
echo str_repeat('A ', 100);
echo "<hr>";
sleep(5);
echo str_repeat('B ', 100);
echo "<hr>";
sleep(5);
echo str_repeat('C', 100);
?>
Außerdem wüßte ich gerne, ob bei den fremd gehosteten Seiten i.d.R. die dio_* Funktionen eincompiliert sind, oder nicht. Wenn Ihr da bei Euch mal schaeuen könntet:
http://de.php.net/manual/de/ref.dio.php
Harzliche Grüße aus http://www.annerschbarrich.de
Tom
Guten Morgen :)
$_SERVER['SERVER_SOFTWARE'] Apache/1.3.27 (Unix) PHP/4.3.1
Und welches OS betreibt Ihr?
Apache/2.0.49 (Linux/SuSE)
Darf ich fragen, welche Bedeutung dem zukommt?
Gruß aus Berlin!
eddi
Hello Eddi,
$_SERVER['SERVER_SOFTWARE'] Apache/1.3.27 (Unix) PHP/4.3.1
Und welches OS betreibt Ihr?
Apache/2.0.49 (Linux/SuSE)Darf ich fragen, welche Bedeutung dem zukommt?
Selbstverständlich. Fragen darfst Du ;-)
Na ich bastele immer noch an den Demoscripten für das File-Locking. Und da ware es doch schön, wenn die auch auf Windows-Hosts funktionieren würden. Das Locking zut es ja, aber die Kontrollausgaben bekomme ich nicht raus bei Windows. Und da muss ich dann ggf. Die Ausgabe unterbinden, damit es keinen RAM-Crash gibt, wenn der Output-Buffer von einem Dauerlauf-Script nicht flushed wird.
Harzliche Grüße aus http://www.annerschbarrich.de
Tom
Hi Tom!
Hello,
ich benötige nochmals Eure Hilfe.
Was steht auf Euren Systemen in
$_SERVER['SERVER_SOFTWARE'] Apache/1.3.27 (Unix) PHP/4.3.1
Und welches OS betreibt Ihr?
Apache/1.3.28 (Linux/SuSE) PHP/4.3.3 mod_perl/1.28
OS: SuSE Linux 9.1
Grüße,
Fabian St.
Kanotix BH7 (Debian unstable mix)
Apache/2.0.50 (Unix)
mod_perl/1.99_13 Perl/v5.8.4 mod_ssl/2.0.50 OpenSSL/0.9.7d PHP/5.0.0 DAV/2
gruss, shev
Hello,
hat hier noch jemand Apache auf Windows laufen? Dann würe dich mich über Antwort auf den O-Post freuen.
Harzliche Grüße aus http://www.annerschbarrich.de
Tom
Hi Tom,
Was steht auf Euren Systemen in
$_SERVER['SERVER_SOFTWARE']
Apache/2.0.49 (Win32) mod_ssl/2.0.49 OpenSSL/0.9.7d PHP/4.3.6 mod_autoindex/color
Und welches OS betreibt Ihr?
Windows 2000 SP4
Dann nochmals eine Bitte an die Windows-User:
Was passiert bei Euch mit dem Buffer, wenn man schon einige Ausgaben gemacht hat und dann erst ob_start() auslöst, dann wiedr einige Ausgaben macht und dann wieder ob_start() auslöst?
Beide Scripte laufen, ohne jegliche Ausgabe zu machen, bis zur Terminierung. Erst danach kommt die komplette Ausgabe.
Außerdem wüßte ich gerne, ob bei den fremd gehosteten Seiten i.d.R. die dio_* Funktionen eincompiliert sind, oder nicht. Wenn Ihr da bei Euch mal schaeuen könntet:
Bei mir (Hosteurope) ist es einkompiliert.
Tom, noch eine andere Anmerkung/Frage:
ich habe gestern etwas programmiert, bei dem ich eine Flatfile-Speicherung vornehme. Dabei habe ich die bei dir oft gelesene Methode benutzt:
das hat bei meinem System _nicht_ funktioniert, er hat die Daten immer an das Ende der Datei gehängt. Dieses Verhalten deckt sich auch mit der Anmerkung unter der Funktionsbeschreibung von rewind() (http://de3.php.net/manual/de/function.rewind.php: "Haben Sie eine Datei im Append-Modus ("a") geöffnet, werden unabhängig von der Dateiposition alle zu schreibenden Daten angehängt.").
Evtl. ist dieses Verhalten ja auch wichtig für deinen Artikel. Daher meine Frage: woran liegt's, oder habe ich was falsch verstanden?
Ich werde heute Abend evtl. mal ein wenig testen.
Gruß,
Andreas.
Hello,
Bei mir (Hosteurope) ist es einkompiliert.
Tom, noch eine andere Anmerkung/Frage:
ich habe gestern etwas programmiert, bei dem ich eine Flatfile-Speicherung vornehme. Dabei habe ich die bei dir oft gelesene Methode benutzt:
- Datei im Modus "a+" öffnen
- Dateizeiger mittels rewind() (danach auch mal testweise mittels fseek()) auf den Anfang der Datei setzen
- schreiben
- ftruncate()
das hat bei meinem System _nicht_ funktioniert, er hat die Daten immer an das Ende der Datei gehängt. Dieses Verhalten deckt sich auch mit der Anmerkung unter der Funktionsbeschreibung von rewind() (http://de3.php.net/manual/de/function.rewind.php: "Haben Sie eine Datei im Append-Modus ("a") geöffnet, werden unabhängig von der Dateiposition alle zu schreibenden Daten angehängt.").
Evtl. ist dieses Verhalten ja auch wichtig für deinen Artikel. Daher meine Frage: woran liegt's, oder habe ich was falsch verstanden?
Ich werde heute Abend evtl. mal ein wenig testen.
Bei Windows muss die Datei mit "ab+" geäffnet wereden, da Windows hier noch echte Textdateien kennt und der Mode ab+ eine Emulation einer Binärdatei öffnet. Wenn man sich die Assembler-Befehler anschaut, die schlussendluch dabei rauskommen, wird einem sowieso schlrcht. C ist Mist, Pascal ist besser.
Wäre nett, wenn Du nochmals rückmelden könntest, ob "ab+" auch Windows funktioniert.
Harzliche Grüße aus http://www.annerschbarrich.de
Tom
Hi Tom,
Wäre nett, wenn Du nochmals rückmelden könntest, ob "ab+" auch Windows funktioniert.
ich hatte die Datei bereits binär geöffnet (das war eine Ungenauigkeit in meinem vorigen Posting). Ich hab jetzt mal ein wenig getestet - es funktioniert bei mir definitiv nicht. Die Daten werden nach dem Öffnen im append mode _immer_ an das Ende der Datei gehängt, unabhängig von der Position des Dateizeigers, z.B.:
<?php
$fh = fopen('./test.txt', 'wb');
fwrite($fh, '123');
fclose($fh);
$fh = fopen('./test.txt', 'a+b');
fseek($fh, 0, SEEK_SET);
echo ftell($fh) . '<br>'; // Ausgabe: 0
fwrite($fh, '456');
fclose($fh);
$fh = fopen('./test.txt', 'rb');
echo fread($fh, filesize('./test.txt')); // Ausgabe: 123456
fclose($fh);
?>
Unter bugs.php.net bin ich außerdem auf zwei Kommentare eines PHP-Supporters gestoßen:
Für mich hört sich das beschriebene Verhalten daher völlig normal an.
Gruß,
Andreas.
Hello,
das ist ja grauenhaft. Allerdings ist der Append-Mode bei DOSen der Text-Datei-Mode, der keine Dateinavigation zulässt. Wenn die das im Quellcode natürlich mit diesem alten INT implementieren in der WinDOS-Version, dann klappt es nicht. Unix kennt diese Unterscheidung nicht.
Wäre nett, wenn Du nochmals rückmelden könntest, ob "ab+" auch bei Windows funktioniert.
ich hatte die Datei bereits binär geöffnet (das war eine Ungenauigkeit in meinem vorigen Posting). Ich hab jetzt mal ein wenig getestet - es funktioniert bei mir definitiv nicht. Die Daten werden nach dem Öffnen im append mode _immer_ an das Ende der Datei gehängt, unabhängig von der Position des Dateizeigers, z.B.:
<?php
$fh = fopen('./test.txt', 'wb');
fwrite($fh, '123');
fclose($fh);
clearstatcache();
$fh = fopen('./test.txt', 'ab+');
echo 'seek: '.fseek($fh, 0, SEEK_SET).'<br />'; # Bei Fehler '-1
echo ftell($fh) . '<br />'; // Ausgabe: 0
clearstatcache();
fwrite($fh, '456');
fclose($fh);$fh = fopen('./test.txt', 'rb');
echo fread($fh, filesize('./test.txt')); // Ausgabe: 123456
fclose($fh);?>
Unter bugs.php.net bin ich außerdem auf zwei Kommentare eines PHP-Supporters gestoßen:
- "'a' mode forces the kernel to always write at the end of the file.
ftell() will give undefined results for append-only streams, as will
seeking. Writing to such a file should always be appended, regardless of the results from ftell()." (http://bugs.php.net/bug.php?id=24071)- "using fseek() and fwrite() on a file opened in append mode will lead to undefined results." (http://bugs.php.net/bug.php?id=29503)
Für mich hört sich das beschriebene Verhalten daher völlig normal an.
Ich lese aber überall nur vom 'a'-Mode und nicht vom 'ab+'-Mode.
Da müssen wir wohl in den Quellcode reinschauen, um zu wissen, wie es gemacht ist. Den für Windows habe ich aber nicht.
Wenn Du das noch einmal mit der clearstatcache-Variante ausprobiern könntest auf Deiner DOSe...
Es wäre auch möglich, das ftruncate($fh,0) direkt nach dem Bewegen des Dateizeigers auf Pos. 0 zu versuchen, und dann erst zu schreiben.
Im DOS-API und auch in den erweiterten Interrupts (INT 21h) ist über Handle kein sequentieller Zugriff mehr vorgesehen, sondern nur noch wahlfreier. Es ist also eine Sacher der DTA-Implementierung bzw. der Blocktreiber, wie sich das System verhält. Das müsste also auch für PHP auf WinDOS zu handhaben sein.
Welches System war das bei Dir?
Harzliche Grüße aus http://www.annerschbarrich.de
Tom
Hi Tom,
Wenn Du das noch einmal mit der clearstatcache-Variante ausprobiern könntest auf Deiner DOSe...
da passiert das gleiche - fseek gibt keinen Fehler zurück. Ausgabe des Scripts insgesamt:
seek: 0
0 (das war ftell())
123456 (das der Inhalt der Datei)
Es wäre auch möglich, das ftruncate($fh,0) direkt nach dem Bewegen des Dateizeigers auf Pos. 0 zu versuchen, und dann erst zu schreiben.
das funktioniert (gerade getestet), ich halte das aber für eine eher schlechte Idee, da die Performance bei großen Dateien doch erheblich schlechter sein dürfte.
Letztendlich verstehe ich nur nicht, warum du eine Datei immer mit "a+b" öffnest, wenn du sie komplett überschreibst (den Inhalt also eh nicht erhalten möchtest). Für diesen Zweck würde sich m.E. eher das Öffnen im Lese-/Schreibzugriff (also "r+b") anbieten, was dann auf allen BS funktionieren müsste, also:
So klappt's dann auch unter Windows (zumindest bei mir).
Welches System war das bei Dir?
Ich arbeite unter Windows 2000 SP4 mit Apache 2.0.49 und PHP 4.3.6
Gruß,
Andreas.
Hello,
Es wäre auch möglich, das ftruncate($fh,0) direkt nach dem Bewegen des Dateizeigers auf Pos. 0 zu versuchen, und dann erst zu schreiben.
das funktioniert (gerade getestet), ich halte das aber für eine eher schlechte Idee, da die Performance bei großen Dateien doch erheblich schlechter sein dürfte.
Bei großen Dateien (ab 1MB) würde ich mir das auch verkneifen. In einem meiner Beispiele wird ein serialisiertes Array in der Datei gespeichert. Da muss man die gesamte Datei neu schreiben.
Letztendlich verstehe ich nur nicht, warum du eine Datei immer mit "a+b" öffnest, wenn du sie komplett überschreibst (den Inhalt also eh nicht erhalten möchtest). Für diesen Zweck würde sich m.E. eher das Öffnen im Lese-/Schreibzugriff (also "r+b") anbieten, was dann auf allen BS funktionieren müsste, also:
Das ist mir klar. Aber da entsteht ein Time Gap, wenn die Datei NICHT vorhanden ist, und daher angelegt werden muss. Der a+-Mode macht das in einem Zug und man muss das Handle nicht wieder hergeben. Bliebe noch der x+-Mode, aber den gibt es erst ab PHP 4.3.2
- fopen('r+b') ## wenn die Datei nicht vorhanden ist, könnte man sie anschließend gleich
## mit w+ aufrufen. Dabei könnte es aber passieren, dass jemand zwischen
## r+ -> Fehler und w+ die Datei bereits gesperrt hat, wovon w+ aber
## bei advisory Locking leider nichts mitbekommt. Und futsch ist die neue
## Datei des Anderen Prozesses.
## bleibt also zum Anlegen nur das Verzeichnis-Locking.
- flock()
- fread()
- Daten bearbeiten
- rewind()
- fwrite()
- ftruncate()
- fclose()
So klappt's dann auch unter Windows (zumindest bei mir).
Welches System war das bei Dir?
Ich arbeite unter Windows 2000 SP4 mit Apache 2.0.49 und PHP 4.3.6
Weißt Du, wo man die Sourcen für PHP auf Windows finden kann? Ich habe schon alles mögliche durchgesucht. Ich will mir das gerne mal ansehen, wie die Filefunktionen implementiert sind.
Erstmal aber noch mein Dank für die Unterstützung; ich hoffe er erreicht Dich auch.
Harzliche Grüße aus http://www.annerschbarrich.de
Tom
Hi,
Das ist mir klar. Aber da entsteht ein Time Gap, wenn die Datei NICHT vorhanden ist, und daher angelegt werden muss. Der a+-Mode macht das in einem Zug und man muss das Handle nicht wieder hergeben.
Ich muss zugeben, dass ich davon ausgegangen bin, die Datei existiert. Dennoch ist der a+-Modus, der zwar in diesem speziellen Fall bequemer (und wahrscheinlich auch schneller) ist, m.E. der falsche Weg.
Bliebe noch der x+-Mode, aber den gibt es erst ab PHP 4.3.2
...und bricht im Falle der Existenz ab. Man müsste also trotzdem auf Existenz prüfen.
- fopen('r+b') ## wenn die Datei nicht vorhanden ist, könnte man sie anschließend gleich
## mit w+ aufrufen. Dabei könnte es aber passieren, dass jemand zwischen
## r+ -> Fehler und w+ die Datei bereits gesperrt hat, wovon w+ aber
## bei advisory Locking leider nichts mitbekommt. Und futsch ist die neue
## Datei des Anderen Prozesses.
## bleibt also zum Anlegen nur das Verzeichnis-Locking.
Ich würde mir das eher so vorstellen:
<?php
if (!file_exists($dateiname))
{
touch($dateiname);
}
fopen($dateiname, 'r+b');
// ...
?>
Das ist IMHO der sauberste Weg. Dieses Vorgehen sollte zeitkritisch kein Problem sein (etwas anderes dürfte der a+-Mode ja auch nicht machen) und das Problem mit dem advisory Locking hätte sich auch erledigt. Alternativ könnte man die Datei natürlich im Falle der Nicht-Existenz mit w+ öffnen und in einem else-Teil mit r+ - das dürfte aber keinen Unterschied machen.
Weißt Du, wo man die Sourcen für PHP auf Windows finden kann? Ich habe schon alles mögliche durchgesucht. Ich will mir das gerne mal ansehen, wie die Filefunktionen implementiert sind.
Leider nicht - ich werde mich aber auch mal auf die Suche machen.
Erstmal aber noch mein Dank für die Unterstützung; ich hoffe er erreicht Dich auch.
tut er. War aber selbstverständlich - dein Artikel interessiert mich auch ;-)
Gruß,
Andreas.
Hello,
Das ist mir klar. Aber da entsteht ein Time Gap, wenn die Datei NICHT vorhanden ist, und daher angelegt werden muss. Der a+-Mode macht das in einem Zug und man muss das Handle nicht wieder hergeben.
Ich muss zugeben, dass ich davon ausgegangen bin, die Datei existiert. Dennoch ist der a+-Modus, der zwar in diesem speziellen Fall bequemer (und wahrscheinlich auch schneller) ist, m.E. der falsche Weg.
Bliebe noch der x+-Mode, aber den gibt es erst ab PHP 4.3.2
...und bricht im Falle der Existenz ab. Man müsste also trotzdem auf Existenz prüfen.
Ja, erst Öffnungsversuch mit r+ und wenn der schief geht die erweiterte Fehlermeldung einholen. Wenn die sagt "File not found" dann mit x+ anlegen. Wenn das auch schief geht, weil inzwischen "File already exists", war eben jemand anders schneller. dann kann man wieder mit r+ anfangen. Wenn das dann endlich klappt, kann man mit dem Lockversuch starten.
- fopen('r+b') ## wenn die Datei nicht vorhanden ist, könnte man sie anschließend gleich
## mit w+ aufrufen. Dabei könnte es aber passieren, dass jemand zwischen
## r+ -> Fehler und w+ die Datei bereits gesperrt hat, wovon w+ aber
## bei advisory Locking leider nichts mitbekommt. Und futsch ist die neue
## Datei des Anderen Prozesses.
## bleibt also zum Anlegen nur das Verzeichnis-Locking.Ich würde mir das eher so vorstellen:
<?php
if (!file_exists($dateiname))
{
touch($dateiname);
}fopen($dateiname, 'r+b');
// ...
?>
Das ist IMHO der sauberste Weg. Dieses Vorgehen sollte zeitkritisch kein Problem sein (etwas anderes dürfte der a+-Mode ja auch nicht machen) und das Problem mit dem advisory Locking hätte sich auch erledigt. Alternativ könnte man die Datei natürlich im Falle der Nicht-Existenz mit w+ öffnen und in einem else-Teil mit r+ - das dürfte aber keinen Unterschied machen.
Das ist leider nicht der richtige Weg, da zwischen file_exists(), touch() und dem nachfolgenden fopen(r+) immer riesen Zeitschlitze existieren, in denen ganz schlimme Sachen passieren können.
Touch arbeitet über Namen und man kann keinen Advisory Lock auf die Datei prüfen, bevor es aufgerufen wird. Allerdings ändert es ja auch nichts am Inhalt, sondern nur an der Inode oder im VFAT.
Weißt Du, wo man die Sourcen für PHP auf Windows finden kann? Ich habe schon alles mögliche durchgesucht. Ich will mir das gerne mal ansehen, wie die Filefunktionen implementiert sind.
Leider nicht - ich werde mich aber auch mal auf die Suche machen.
Erstmal aber noch mein Dank für die Unterstützung; ich hoffe er erreicht Dich auch.
tut er. War aber selbstverständlich - dein Artikel interessiert mich auch ;-)
Aber ich komme vom Hundertstel ins Tausendstel. Und schließlich soll ja nchher alles stimmen, was ich da so zusammenschreibe. Ich suche jetzt erstmal die Stelle in den Sourcen für Linux, an der fopen(a+) definiert ist. Mal sehen, ob ich da durchsteige.
Harzliche Grüße aus http://www.annerschbarrich.de
Tom