Michel: Ein Graus - File lock

Hi zusammen,

ich weiss, es wurde schon x-mal diskutiert. Nie befriedigend wie ich finde. File locking unter Unix. Schaut Euch das mal an, unter dem Aspekt, dass ich eine Datei lese, den Inhalt auf irgendwas prüfe, den Inhalt veraendere und die Datei dann neu schreibe:

open(DATA, "<datei.dat");
flock (DATA,2);
  @temp = <DATA>;
close(DATA);

Ich weiss, dass ich hier ein flock (DATA,1) setzen muesste, ich will aber exclusiv locken. Erstmal egal. Weiter...

$temp[12] = "Neuer text"; # Hier bastel ich also an meinem Inhalt

open(DATA, ">datei.dat"); # und schreib neu
flock (DATA,2);
foreach $mline (@temp) {print DATA $mline . "\n";};
close(DATA);

Soweit so schlecht. Denn was kann alles zwischen den beiden "Open" passieren? Alles! Ich bin ja nicht der einzige Prozess. Ausserdem schuetzt flock (DATA,2) nicht vor einem Lesen der (vielleicht gerade leeren Datei weil geschrieben wird) und und und. Kurz, dieser Code ist Muell.

Simpel: HILFE! WIE IST ES RICHTIG?

Ich hab all das ueber selbst angelegte Semaphoren etc. gelesen, auch das ist keine Lösung. Wie einige richtig erkannt haben gibt es auch dort kritische Momente wo eine Abfrage schieflaufen muss.

Sicher, ich könnte "richtige" Datenbanken nehmen, hab ich aber im Moment nicht und irgendwie muss das doch gehen.

Danke im voraus.

Verzweifelt (Datei schon einmal zerschossen)

Michel

  1. Hallo Michel,

    warum nicht so ?

    open (FILE,"+<$file") or die # open file
    flock(FILE,2);     # lock file exclusive
    seek (FILE,0,0);    # position at start

    @records = <LOGFILE>;

    ... weitere Verarbeitung

    seek (FILE,0,0);    # position at start
    print (FILE @newrecs);
    truncate (LOGFILE,tell(LOGFILE));

    flock(FILE,8);     # release lock
    close(FILE);

    und in anderen cgis, die nur lesen:

    open (FILE,"$file") or die # open file
    flock(FILE,1);    # lock file shared

    ... weitere Verarbeitung

    viele Grüße Günter

    1. warum nicht so ?

      open (FILE,"+<$file") or die # open file
      flock(FILE,2);     # lock file exclusive
      seek (FILE,0,0);    # position at start

      @records = <LOGFILE>;

      [...]

      Du meinst @records = <FILE>; richtig?

      Ok, ich wuesste nicht warum nicht. Wenn das die absolut sichere Methode ist bin ich Dir sehr dankbar. Ist sie es?

      Verstehe nur nicht warum das nicht oefter verwendet wird. Selbst "Profis" schreiben Semaphoren und all das. Z.B. der Author von Webadverts. Den halte ich fuer einigermassen faehig aber er benutzt Semaphoren. Naja, kann sein, dass er flock umgehen will weil manch ein Server das nicht unterstuetzt.

      Bis dann

      Gruss Michel

      1. Hallo Michel,

        Du meinst @records = <FILE>; richtig?

        ja, kam von cut&paste ...

        Ok, ich wuesste nicht warum nicht. Wenn das die absolut sichere Methode ist bin ich Dir sehr dankbar. Ist sie es?

        habe damit noch nie Probleme gehabt (unter Linux) ...

        Verstehe nur nicht warum das nicht oefter verwendet wird. Selbst "Profis" schreiben Semaphoren und all das. Z.B. der Author von Webadverts. Den halte ich fuer einigermassen faehig aber er benutzt Semaphoren. Naja, kann sein, dass er flock umgehen will weil manch ein Server das nicht unterstuetzt.

        ... tja, rätselhaft ... ;-)

        Günter

        1. Lieber Günter,

          Ok, ich wuesste nicht warum nicht. Wenn das die absolut sichere Methode ist bin ich Dir sehr dankbar. Ist sie es?
          habe damit noch nie Probleme gehabt (unter Linux) ...

          Viele Zugriffe? Sprich hochfrequentierte Seiten?

          Gruss

          Michel

          1. Hallo Michel,

            Viele Zugriffe? Sprich hochfrequentierte Seiten?

            privat eher weniger (purpurhain.de ist nur meine öffentliche Spielwiese und nicht jederman|fraus Geschmack),
            im Geschäft - nur Intranet - ca. 20-30 / Min.

            Viele Grüße Günter

    2. warum nicht so ?

      open (FILE,"+<$file") or die # open file
      flock(FILE,2);     # lock file exclusive

      Da faellt mir noch, flock (FILE,2); sperrt ja nicht das Lesen. Wenn aber ein anderer Prozess hier...

      print (FILE @newrecs);

      liest waehrend grad geschrieben wird, dann wird der lesende Prozess doch auf jeden Fall unvollstaendige Daten bekommen?

      Was meinst Du?

      Gruss

      Michel

      1. Hallo Michel,

        liest waehrend grad geschrieben wird, dann wird der lesende Prozess doch auf jeden Fall unvollstaendige Daten bekommen?

        Was meinst Du?

        siehe mein 1stes Posting
        open (FILE,"$file") or die # open file
        flock(FILE,1);    # lock file shared

        ... weitere Verarbeitung

        dazu auch ein Auszug aus der Active Perl Dokumentation:

        "This means that files locked with flock() may be modified by programs that do not also use flock()."

        viele Grüße Günter

    3. warum nicht so ?

      open (FILE,"+<$file") or die # open file

      [..]

      Hi Günter,

      und jetzt haette ich noch gern gewusst wie diese Funktion eine Datei erzeugt wenn sie nicht existiert. Das macht sie naemlich nicht.

      Ansonsten habe ich sie schon recht erfolgreich am Laufen (bisher ist alles heil geblieben).

      Nun habe ich es so geloest, dass ich vorher checke ob die Datei existiert und wenn nicht mit open (FILE, ">>datei.dat");close(FILE); diese erzeuge. Erscheint mir aber nicht sehr elegant.

      Da ich zwar ">>" und ">" und "<" verstehe, nicht aber "+<" weiss ich nicht recht was ich machen muss.

      Danke!

      Gruss

      Michel

      1. Hallo Michel,

        und jetzt haette ich noch gern gewusst wie diese Funktion eine Datei erzeugt wenn sie nicht existiert. Das macht sie naemlich nicht.
        Ansonsten habe ich sie schon recht erfolgreich am Laufen (bisher ist alles heil geblieben).
        Nun habe ich es so geloest, dass ich vorher checke ob die Datei existiert und wenn nicht mit open (FILE, ">>datei.dat");close(FILE); diese erzeuge. Erscheint mir aber nicht sehr elegant.

        ich wüßte auch keinen besseren Weg als

        if(!stat($file))
        {
         open (FILE,">$file");  # create file
         close (FILE;
        }

        open (FILE,"+<$file") or die();

        ....
        ...
        ..

        Da ich zwar ">>" und ">" und "<" verstehe, nicht aber "+<" weiss ich nicht recht was ich machen muss.

        Zitat:
        If the filename begins with '<' or nothing, the file is opened for input. If the filename begins with '>',
        the file is truncated and opened for output, being created if necessary. If the filename begins with
        '>>', the file is opened for appending, again being created if necessary. You can put a '+' in front
        of the '>' or '<' to indicate that you want both read and write access to the file; thus '+<' is
        almost always preferred for read/write updates--the '+>' mode would clobber the file first. You can't
        usually use either read-write mode for updating textfiles, since they have variable length records. See the
        -i switch in perlrun for a better approach. The file is created with permissions of 0666 modified by the
        process' umask value.

        Viele Grüße Günter