Schrift
Wiki:Tipp zum Debugging: use Data::Dumper; local $Data::Dumper::Useqq = 1; print Dumper \@var;
[thread]12681[/thread]

[PHP] mehrfaches Schreiben in eine Logdatei bei mehreren gleichzeitigen Zugriffen?

Leser: 1


<< >> 10 Einträge, 1 Seite
Gast Gast
 2008-10-28 14:23
#115789 #115789
Hallo,

ich habe eine Frage zur Vorgehensweise:

Auf einer Webseite wird mittels index.php ein zufälliger Spruch/Text (via fortune) angezeigt. Soweit, so gut.
Dieser Text wird auch in eine selbst angelegte log-datei ins selbe Verzeichnis der index.php geschrieben. Das klappt auch.

Was passiert aber nun, wenn mehrere Browser gleichzeitig auf diese Webseite (index.php) zugreifen?

Wird die log-datei zerhackt, weil mehrfach beschrieben?
Oder wird -falls ja, warum?- alles hintereinander ins log geschrieben?

hier ein Auszug aus der index.php.

Code (perl): (dl )
1
2
3
4
5
6
7
8
9
$APO = "zufälliger Spruch";

$versuche = 0;

$datum = date("l dS of F Y H:i:s")." (".$_SESSION["username"].")";

$fp = fopen("./log-datei.log","a+");
fputs($fp, "###\n###".$datum." (anzahl versuche: ".$versuche."):\n".$APO."\n");
fclose($fp);


Mich würde es natürlich interessieren, das die log-datei nicht zerschrieben wird und wie ich dies erreiche.
ideen und/oder quellen willkommen :-)
pq
 2008-10-28 14:32
#115793 #115793
User since
2003-08-04
12208 Artikel
Admin1
[Homepage]
user image
ich hab das ganze mal ins php-forum verschoben (vorher: Webprogrammierung mit Perl)
Always code as if the guy who ends up maintaining your code will be a violent psychopath who knows where you live. -- Damian Conway in "Perl Best Practices"
lesen: Wiki:Wie frage ich & perlintro Wiki:brian's Leitfaden für jedes Perl-Problem
Gast Gast
 2008-10-28 18:54
#115803 #115803
Schon mal davon gehört, dass beim Schreiben auch die Datei gesperrt werden muss, damit nicht zwei Prozesse gleichzeitig das Log zerhauen?

http://de.php.net/manual/de/function.flock.php
Gast Gast
 2008-11-08 02:03
#116091 #116091
pq+2008-10-28 13:32:16--
ich hab das ganze mal ins php-forum verschoben (vorher: Webprogrammierung mit Perl)

danke und entschuldigung für das doppelposting. habe zwar via suche nach meinem topic gesucht, allerdings nichts gefunden.
Gast Gast
 2008-11-08 02:26
#116094 #116094
Gast+2008-10-28 17:54:38--
Schon mal davon gehört, dass beim Schreiben auch die Datei gesperrt werden muss, damit nicht zwei Prozesse gleichzeitig das Log zerhauen?

Vielen dank für den Linkhinweis.

Nein, ich wusste davon nichts, habe es nur vermutet, allerdings ohne Beweis.

Nun weiss ich zwar immernoch nichts genaues, habe aber auf der Seite in den Codebeispielen die ein Beispiel (Klasse: SafeWriter) für verzögertes Schreiben im Falle einer gesperrten Datei gefunden.
Da ich Klassenprogrammierung nicht kenne habe ich eine normale Funktion daraus gemacht, eingebunden und schreibe nun so das log:

Code: (dl )
writeLog("log-datei.log","a+", $datum."\n".$APO."\n");


Die Funktion sieht so aus:
[php]<?php
// suggested mode 'a' for writing to the end of the file
function writeLog($path, $mode, $data)
{
$fp = fopen($path, $mode);
$retries = 0;
$max_retries = 30;
if (!$fp) {
// failure
return false;
}
// keep trying to get a lock as long as possible
do {
if ($retries > 0) {
usleep(rand(1, 10000));
}
$retries += 1;
} while (!flock($fp, LOCK_EX) and $retries <= $max_retries);
// couldn't get the lock, give up
if ($retries == $max_retries) {
// failure
return false;
}
// got the lock, write the data
fwrite($fp, "$data");
// release the lock
flock($fp, LOCK_UN);
fclose($fp);
// success
return true;
}
?>[/php]
Sehe ich das richtig, das, falls das Script (innerhalb der index.php) von 2 Browsern gleichzeitig aufgerufen wird und eine Instanz die log-datei sperrt, die andere Instanz des Scriptes einfach solange wartet, bis es die log-datei entsprerrt vorfindet und dann schreibt?

//Modedit GwenDragon: PHP-Code in PHP-Boardtags gestellt
Gast Gast
 2008-11-08 08:20
#116097 #116097
Genau.

Instanz 1 sperrt die Datei, schreibt seine Sachen.
Instanz 2 waretet maximal 30*rand(1000) Millisekunden (durchschnittlich 15 Sekunden) bis die Datei Frei gegen wird, sperrt es selber und schreit seine Sachen.

Die maximale Wartezeit wird sehr wahrscheinlich nicht erreicht, da das schreiben sehr schnell geht und es wohl kaum riesige Datenmengen sind die geschrieben werden.
Das "rand" wurde wohl eingefügt, das, wenn mehr als zwei Prozesse schreiben wollen, nicht alle zum selben Zeitpunkt die Datei an sich zu binden versuchen.

Denke aber daran, das eine Datei immer wieder entsperrt werden muss, denn sonst kann es unter Umständen zu Hängern kommen, da die Datei über einen längeren Zeitraum gesperrt bleiben könnte. An sich wird die Sperrung der Datei aufgehoben wenn das Filehandle geschlossen wir, aber besser man ist vorsichtig. (Es kommt ganz darauf an wie das Betriebssystem und der Interpreter mit Filehandles umgeht. Eventuell bleiben die Dateien im Hintergrund noch eine Weile geöffnet)
Gast Gast
 2008-11-10 00:04
#116144 #116144
Vielen dank für Deine ausführliche Beschreibung. Das hat sehr zum Verständnis beigetragen.

Gast+2008-11-08 07:20:16--
Denke aber daran, das eine Datei immer wieder entsperrt werden muss

Soweit ich den Code (aus der Funktion) verstehe, wird die Datei wieder entsperrt. Es sollte sich also alles im Rahmen befinden.
Oder war dies nur ein allgemeiner Hinweis?
Danke nocheinmal.
pq
 2008-11-10 11:22
#116152 #116152
User since
2003-08-04
12208 Artikel
Admin1
[Homepage]
user image
ich weiss nicht, wie das in php ist, aber in perl sollte man *kein* unlock machen, das wird automatisch
mit close gemacht, und wenn man es vorher macht, hat man automatisch wieder eine race
condition und dann nützt das ganze lock nix. es gibt nur ein paar situationen, in denen
ein unlock sinn ergibt.
Always code as if the guy who ends up maintaining your code will be a violent psychopath who knows where you live. -- Damian Conway in "Perl Best Practices"
lesen: Wiki:Wie frage ich & perlintro Wiki:brian's Leitfaden für jedes Perl-Problem
Gast Gast
 2008-11-11 14:35
#116192 #116192
pq+2008-11-10 10:22:29--
ich weiss nicht, wie das in php ist, aber in perl sollte man *kein* unlock machen, das wird automatisch
mit close gemacht, und wenn man es vorher macht, hat man automatisch wieder eine race
condition und dann nützt das ganze lock nix. es gibt nur ein paar situationen, in denen
ein unlock sinn ergibt.


ok, ich verstehe, aber ich denke mal, da hier im Quellcode
Code: (dl )
1
2
27:         flock($fp, LOCK_UN);
28: fclose($fp);

das Entsperren und das Schliessen des Filehandlers direkt hintereinander geschehen, sollte es -jedenfalls in meinem pers. Fall- keinen großen Unterschied machen.

Vielen Dank für die Anregungen, ich werde mir jetzt erstmal anlesen, was eine RaceCondition ist... :-)
murphy
 2008-11-11 15:53
#116194 #116194
User since
2004-07-19
1776 Artikel
HausmeisterIn
[Homepage]
user image
[quote="Gast+2008-11-11 13:35:14--"]
pq+2008-11-10 10:22:29--
[...]
ok, ich verstehe, aber ich denke mal, da hier im Quellcode
Code: (dl )
1
2
27:         flock($fp, LOCK_UN);
28: fclose($fp);

das Entsperren und das Schliessen des Filehandlers direkt hintereinander geschehen, sollte es -jedenfalls in meinem pers. Fall- keinen großen Unterschied machen.
[...]


Das ist sehr wohl ein großer Unterschied, wenn Deine Ausgabe gepuffert ist (was sie vermutlich auch bei PHP standardmäßig immer ist) und Du vor dem Entsperren der Datei nicht den Puffer leerst.

Es kann dann nämlich folgendes passieren: Prozess 1 öffnet die Datei, sperrt sie, schreibt Daten und entsperrt die Datei – die Daten liegen jetzt aber noch im RAM-Puffer und nicht in der Datei. Nun kommt Prozess 2 öffnet und sperrt die Datei, denn Prozess 1 hat sie ja schon entsperrt, und schreibt Daten hinein. Prozess 2 schreibt aber zufällig eine ganze Menge Daten in die Datei, also wird zwischendurch der Puffer einmal geleert. Zu diesem Zeitpunkt kommt nun zufällig wieder Prozess 1 an die Reihe, schließt die Datei und leert dabei seine Puffer. Danacht schreibt Prozess 2 weitere Daten, entsperrt die Datei, schließt sie und leert dabei seine Puffer. Ergebnis: In der Datei stehen hinterher zunächst Daten von Prozess 2 dann von Prozess 1 und dann wieder von Prozess 2, wobei der Übergang zwischen den Blöcken an völlig sinnlosen Stellen liegen kann. Durch die Sperre wurde also nichts gewonnen.
When C++ is your hammer, every problem looks like your thumb.
<< >> 10 Einträge, 1 Seite



View all threads created 2008-10-28 14:23.