1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
#!/usr/bin/perl -w use strict; use warnings; use Fcntl qw (:DEFAULT :flock); my $datei = '/meinpfad/test.dat'; my $err; sysopen(my $fh,$datei,O_RDONLY) or $err = $!; if (!defined $err) { my $flock = flock($fh,LOCK_EX|LOCK_NB); if ($flock) { print "Geht los\n"; my $ul = unlink($datei); print "unlink: $ul - >$!<\n"; } else { print "Anderweitig gesperrt\n"; } }
QuoteGeht los
unlink: 0 - >Permission denied<
QuoteGeht los
unlink: 1 - >Inappropriate ioctl for device<
my %opened=map{ $_ => 1 }grep{ !/^\w+:\[?\w+\]?$/ }map{ readlink }glob( "/proc/*/fd/*" );
2013-04-07T07:48:47 biancaAuf dem Linux hingegen grätscht das unlink anscheinend in jeglichen Zugriff hinein und löscht gnadenlos. Zwar wird $! gesetzt aber das nützt mir nach dem unlink ja nichts mehr.
2013-04-07T11:44:44 pq2013-04-07T07:48:47 biancaAuf dem Linux hingegen grätscht das unlink anscheinend in jeglichen Zugriff hinein und löscht gnadenlos. Zwar wird $! gesetzt aber das nützt mir nach dem unlink ja nichts mehr.
wie kommst du darauf? wie lange arbeitest du schon mit perl?
$! ist nur bei fehlern aussagekräftig. wenn das unlink erfolgreich ist, hat dich $! nicht zu interessieren. da steht immer irgendwas drin.
2013-04-07T11:48:59 RaubtierWie ich schon schrieb: das $! wird vom sysopen gesetzt (nur eben in Biancas Programm nicht ausgegeben). Ist aber eben völlig irrelevant.
Edit: warum ist das eigentlich so? Ich würde aus Performancegründen erwarten, dass $! nicht angefasst wird, wenn kein Fehler auftritt. Oder macht sysopen intern irgendwas, das diesen Fehler verursacht, der aber für den sysopen-Erfolg irrelevant ist?
2013-04-07T13:05:37 pq$! wird nur im fehlerfall gesetzt. ansonsten enthält es "irgendwas". warum sysopen es setzt, müsstest du mir noch erklären.
1 2 3 4 5 6
# close ... my %opened; if($^O=~/linux/i) { %opened=map{ $_ => 1 }grep{ !/^\w+:\[?\w+\]?$/ }map{ readlink }glob( "/proc/*/fd/*" ); } unlink $file if(-z $file and !$opened{$file});
Guest werSicher geht das auch so:
Öffnen
Locken
Löschen if -z
Schließen
2013-04-07T13:16:36 biancaDanke für alle Antworten.
Zum Hintergrund: Das Dateihandling ist gekapselt in einer sub. Diese sub macht in dieser Reihenfolge folgendes:
1. sysopen
2. flock
3. binmode
4. seek
5. readline
6. truncate
7. print
8. close
9. unlink if -z
Und genau damit ist mir letztens eine Datei verloren gegangen. War nur ein unwichtiger Chat aber schon bei zwei Leuten hat das unlink offensichtlich einmal mitten rein gegrätscht, denn plötzlich war der Chat leer :(
Mal davon abgesehen, dass man das mit einer DB sicher einfacher hinbekommt und auch die Frage berechtigt ist, warum ich leere Dateien nicht haben will, möchte ich trotzdem gern das Problem lösen.
Daher mal ganz allgemein, wie würdet ihr das machen?
Weitere Prämisse: Es bestehen keine Admin-Rechte!
Danke für alle Tipps.
2013-04-23T22:56:34 thomas38Ja, und weiter?Du öffnest die Datei (Schritt 1) und versuchst anschließend ein flock (Schritt 2). Somit ist sie bereits geöffnet.
2013-04-23T22:56:34 thomas38Es geht hierbei nicht nur um eine Datei sondern um eine beim Programmstart noch nicht bekannte Anzahl Dateien.Meine Empfehlung:
Eine eigene Lock-Datei beim Start des Programms anlegen, sofern sie noch nicht existiert (als _ein_ Systemaufruf). Es ist kein Fehler, wenn die Datei bereits existiert.
2013-04-24T07:39:59 RaubtierThomas schlägt die ein Locking vor mithilfe einer zusätzlichen, festen Datei vor.
2013-04-24T08:23:47 biancaJa, habe ich verstanden.
QuoteWie gesagt, es geht nicht nur um eine Datei und ich habe keine Lust, mir ein Paralleluniversum an Dateien aufzubauen :)
2013-04-24T13:03:44 RaubtierDas ist ja auch nicht der Fall. Es gibt genau eine andere Datei.
2013-04-24T15:18:59 pqwenn du 40 verschiedene skripte hast, die sich alle mit denselben dateien beschäftigen, und wenn du keinen gemeinsamen code hast, der den zugriff darauf kapselt (dann könntest du das locking mit der lockdatei zentral in einem modul machen), dann machst du was falsch.
use Lock;
1 2 3 4 5 6 7 8
sub mach_was_mit_dateien { irgendwas_das_kein_lock_braucht; { my $lock = Lock::getGlobalLock(); operationenen_die_lock_brauchen; } rest_der_kein_lock_braucht; }
QuoteMan wird aber wohl oft nicht gleich den ganzen Prozess locken wollen, sondern nur die Teile, die mit der Dateibehandlung zu tun haben.