Andreas: Datei für andere Zugriffe sperren

Hallo!
ich brauch eine eindeutige ID, da gibts zwar auch andere Möglichkeiten, aber da es nicht viele Zugriffe gibt dachte ich die ID in einer txt zu speichern und jeweils zu erhöhen wäre die sicherste Variante, aber nur wenn die Datei während des Zugriffes gesperrt bleibt! Das wichtigste ist das kein doppelte IDs entstehen dürfen, das ist das oberste Gebot. Das muß möglichst mit 100%iger Sicherheit ausgeschlossen werden.

Das doofe an der Datei Version: Ich muß die Datei ja 2 mal öffnen, einmal zum lesen und einemal zum schreiben, oder?

$data = fopen($file, "r");
$count = fread($data, filesize($file));
fclose($data);

$count++;

$data = fopen($file, "w+");
fwrite($data, $count);
fclose($data);

Wie kann ich die Datei so lange für andere Zugriffe sperren? Oder was gibt es fü bessere Möglichkeirten(keine DB)? Die anderen Möglichkeiten mit time() und rand()... sind doch alle nicht wirklich eindeutig, oder?
Bis jetzt habe ich das immer mit der DB gemacht, aber das geht diesmal leider nicht. Was würdet Ihr empfehlen?

Grüße
Andreas

  1. Hallo,

    Das doofe an der Datei Version: Ich muß die Datei ja 2 mal öffnen, einmal zum lesen und einemal zum schreiben, oder?

    1x reicht und dazu Einsatz von flock():

    $data = fopen($file, "r+");
    flock($data,2);
    $count = fread($data,filesize($file));
    $count++;
    rewind($data);
    fwrite($data, $count);
    flock($data,3);
    fclose($data);

    MfG, Thomas

    1. Hallo,

      Das doofe an der Datei Version: Ich muß die Datei ja 2 mal öffnen, einmal zum lesen und einemal zum schreiben, oder?

      1x reicht und dazu Einsatz von flock():

      $data = fopen($file, "r+");
      flock($data,2);
      $count = fread($data,filesize($file));
      $count++;
      rewind($data);
      fwrite($data, $count);
      flock($data,3);
      fclose($data);

      flock() funktioniert nicht auf NFS und verschiedenen anderen vernetzten Dateisystemen. Für weitere Detail konsultieren Sie bitte Ihre Betriebssystemdokumentation.

      Bei einigen Betriebssystemen ist flock() auf dem Prozesslevel implementiert. Wenn Sie ein multithreaded Server API wie ISAPI benutzen können Sie sich nicht auf flock() verlassen, um Dateien vor anderen PHP-Skripten zu schützen, welche in parallelen Threads der gleichen Server-Instanz laufen!

      http://www.php.net/manual/de/function.flock.php

      1. Hallo,

        Bei einigen Betriebssystemen ist flock() auf dem Prozesslevel implementiert. Wenn Sie ein multithreaded Server API wie ISAPI benutzen können Sie sich nicht auf flock() verlassen, um Dateien vor anderen PHP-Skripten zu schützen, welche in parallelen Threads der gleichen Server-Instanz laufen!

        Ich kann nur berichten, dass ich bisher auf Sites unter Apache/Linux noch keine Probleme mit flock() hinsichtlich Dateiinkonsistenzen hatte.

        MfG, Thomas

    2. Hallo,

      Das doofe an der Datei Version: Ich muß die Datei ja 2 mal öffnen, einmal zum lesen und einemal zum schreiben, oder?

      1x reicht und dazu Einsatz von flock():

      $data = fopen($file, "r+");
      flock($data,2);
      $count = fread($data,filesize($file));
      $count++;
      rewind($data);

      aha, das kannte ich nicht, wenn das denn so geht, bei mir ging das nämlich nie, aber ich hatte haltr kein rewind() benutzt!

      fwrite($data, $count);
      flock($data,3);
      fclose($data);

      Eine Frage noch, sollte man das flock nicht lieber vo bzw. nach dem öffnen bzw. schließen machen? Denn so könnte ja jemand zwischen

      $data = fopen($file, "r+");
      flock($data,2);

      ebenfalls die Datei öffnen, oder? Klar, der Zufall müßte einem da schon einen gehörigen Streich spielen, in der kurzen Zeit, aber es sind eben keine 100%, oder?

      Geht es nicht 100%ig ohne externe Software?

      Jedenfalls vielen Dank!

      Viele Grüße
      Andreas

      1. Hallo,

        Eine Frage noch, sollte man das flock nicht lieber vo bzw. nach dem öffnen bzw. schließen machen? Denn so könnte ja jemand zwischen

        $data = fopen($file, "r+");
        flock($data,2);

        ebenfalls die Datei öffnen, oder?

        Dann wuerde aber die von flock() benoetigte Dateireferenz $data noch nicht oder nicht mehr existieren.

        MfG, Thomas

        1. Hi!

          Dann wuerde aber die von flock() benoetigte Dateireferenz $data noch nicht oder nicht mehr existieren.

          Ja, schade, aber dann ist es wohl auch nicht 100%ig. Aber schonmal ein deutlich Steigerung zu einer Variante!

          Grüße
          Andreas

  2. $data = fopen($file, "r");
    $count = fread($data, filesize($file));
    fclose($data);

    $count++;

    $data = fopen($file, "w+");
    fwrite($data, $count);
    fclose($data);

    so gehts leider nicht... du musst ja immer erst die datei öffnen *** lesen *** schreiben schliessen

    an den *** stellen kann das ganze ja schon jemand anderes gestartet haben und dann kommt alles durch einander. leider kenne ich keine lösung.. sorry

    luca

  3. ich brauch eine eindeutige ID, da gibts zwar auch andere Möglichkeiten, aber da es nicht viele Zugriffe gibt dachte ich die ID in einer txt zu speichern und jeweils zu erhöhen wäre die sicherste Variante, aber nur wenn die Datei während des Zugriffes gesperrt bleibt!

    Mit dem Semaphore-Mechnismus kannst Du systemweit eine Sperre einrichten, die nur von einer bestimmten Anzahl Prozesse gleichzeitig durchgangen werden kann (in Deinem Fall: nur einer): http://www.php.net/manual/de/ref.sem.php.

    Oder was gibt es fü bessere Möglichkeirten(keine DB)? Die anderen Möglichkeiten mit time() und rand()... sind doch alle nicht wirklich eindeutig, oder?

    Das kommt auf die Anwendung an. Wenn Du befürchtest, pro Sekunde mehrere tausend Zugriffe zu bekommen, kannst Du mit einer Kombination aus time() und rand() natürlich Pech haben. Bei zwei Zugriffen alle halbe Stunde ist die Wahrscheinlichkeit gleicher IDs hingegen vorsichtig ausgedrückt eher gering.

    Unter Umständen erzeugt Dein Webserver auch bereits selber eine ID. Lass Dir per phpinfo() die Umgebungsvariablen ausgeben, eventuell taucht da etwas in der Richtung UNIQUE_ID auf (siehe http://httpd.apache.org/docs/mod/mod_unique_id.html).

    Gruß,
      soenk.e

    1. Hi!

      Unter Umständen erzeugt Dein Webserver auch bereits selber eine ID. Lass Dir per phpinfo() die Umgebungsvariablen ausgeben, eventuell taucht da etwas in der Richtung UNIQUE_ID auf (siehe http://httpd.apache.org/docs/mod/mod_unique_id.html).

      Tatsache! Und das Überschneidet sich auch nicht mit alten IDs?

      Grüße
      Andreas

      1. Unter Umständen erzeugt Dein Webserver auch bereits selber eine ID. Lass Dir per phpinfo() die Umgebungsvariablen ausgeben, eventuell taucht da etwas in der Richtung UNIQUE_ID auf (siehe http://httpd.apache.org/docs/mod/mod_unique_id.html).

        Tatsache! Und das Überschneidet sich auch nicht mit alten IDs?

        Was heißt "alte IDs"? Wenn Du damit irgendwelche Nummern meinst, die Du bereits auf andere Art und Weise erzeugt hast: Kein System kann Dir das garantieren, den kein System kann auf alle anderen System achten. Da müsstest Du dann schon noch selber einen Riegel vorsetzen, um IDs dieser beiden Systeme zu unterscheiden.

        Lies Dir die Beschreibung zu mod_unique_id am Besten mal durch. Die IDs basieren auf Maschinenname, Prozess-ID und der aktuellen Zeit und dürften somit für Deine Zwecke wasserdicht sein: ein Prozess kann nur eine Anfrage pro Zeitpunkt bearbeiten, dazu kommt noch der eindeutige Rechnername, der die Angelegenheit sogar über mehrere Server hinweg einsetzbar macht.

        Gruß,
          soenk.e

  4. Moin!

    ich brauch eine eindeutige ID, da gibts zwar auch andere Möglichkeiten, aber da es nicht viele Zugriffe gibt dachte ich die ID in einer txt zu speichern und jeweils zu erhöhen wäre die sicherste Variante, aber nur wenn die Datei während des Zugriffes gesperrt bleibt! Das wichtigste ist das kein doppelte IDs entstehen dürfen, das ist das oberste Gebot. Das muß möglichst mit 100%iger Sicherheit ausgeschlossen werden.

    Auch wen Sönke mit mod_unique_id schon deine Lösung gefunden hat: Eindeutige IDs gibts auch mit Sessions und mit der Funktion tempnam(), welche einen eindeutigen Namen für temporäre Dateien in einem bestimmten Verzeichnis generiert. Diese beiden Methoden wären in meinen Augen durchaus geeignet.

    Außerdem kennt PHP den Befehl uniqid(), welcher eindeutige IDs generiert. SelfPHP empfiehlt, zusätzlich noch mit md5() zu arbeiten - das ist in meinen Augen aber Blödsinn, weil gleiche Eingaben auch gleiche Ausgaben zur Folge haben: Entweder uniqid() liefert eindeutige IDs, oder nicht. Die Kommentare auf php.net sind wie immer aufschlußreich. :)

    http://www.php.net/manual/en/function.uniqid.php

    - Sven Rautenberg