Ich kriegs nicht gebacken...mit flock
Alain
- perl
Guten Morgen,
Ich habe da ein beispiel an dem ich zur zeit nicht weiter komm.
Ich finde flock eine gute methode um daten zu schützen bevor sie von einem zweiten zugriff
benutzt werden,aber in meinem beispiel geht das wahrscheinlich nicht so
wie ich das will.
Ich möchte eine datei einlesen und beschreiben ohne dass der alte inhalt gelöscht wird
und diese datei sollte solange von anderen zugriffen geschützt sein bis
das einlesen sowie das geschriebene abgeschlossen ist.
Hier ist das beispiel:
sub check
{
use Fcntl ':flock'; #hier wird eingelesen ob das zu schreibende schon vorhanden ist
$Zugriffe = 0;
open(DATEN,"<$logfile") || &Dead('Cannot open file');
flock(DATEN,LOCK_EX);
while (<DATEN>){
/$etwas_geschriebenes/ ? $Zugriffe = $Zugriffe + 1 : $Zugriffe = $Zugriffe;
}
if ($Zugriffe >= 1) #wenn es vorhanden ist
{
&Dead(); #dann verlasse den weiteren vorgang
}
else
{
close (DATEN);
##hier ist das problem,wo ein zweiter zugriff der die daten wieder einliest,
den weiteren vorgang stören könnte bzw. die daten dann nochmals schreibt,
weil er in dem moment bevor er die daten schreibt ja schon einliest
und nicht weiss dass die daten bereits geschrieben wurden.##
open(DATEN,">>$logfile") || &Dead('Cannot open file'); #ansonsten schreibe den text in die log
flock(DATEN,LOCK_EX);
print DATEN "$etwas_geschriebenes\n";
close (DATEN);
&email();
}
}
------------
Das problem hatte ich als jemand in einer sekunde zweimal das script aufgerufen hatte.
Vielleicht gehts ja so,denn das script ist nun so (wie es oben steht abgeändert worden).
Oder weiss jemand eine bessere idee?
Grüsse
Alain
Hi!
close (DATEN);
##hier ist das problem
Schon mal richtig erkannt. Gut, dann musst Du nur noch in http://forum.de.selfhtml.org/archiv/2002/6/13484/ die Loesung nachlesen. ;-)
So long
Neben dem was Colocybe dir schon gezeigt hat...
use Fcntl ':flock'; #hier wird eingelesen ob das zu schreibende schon vorhanden ist
Das einbinden der Module ist übersichtlicher (IMHO) wenn man es am Anfang des Skriptes macht.
$Zugriffe = 0;
Du solltest DRINGEND use strict verwenden, da das dich gerade in der Entwicklungphase vor vielen vielen Fehlern bewahrt und dir beim Debuggen sehr hilft.
Außerdem sollten Variabeln nicht mit einem Großbuchstaben beginnen http://perldoc.com/perl5.8.0/pod/perlstyle.html
open(DATEN,"<$logfile") || &Dead('Cannot open file');
Hier kannst du deiner Fehlerroutine noch $! mitgeben, dann weißt du auch warum dein Programm sterben musste.
/$etwas_geschriebenes/ ? $Zugriffe = $Zugriffe + 1 : $Zugriffe = $Zugriffe;
Das hatten wir doch letztens erst:
Besser so:
$Zugriffe = /$etwas_geschriebenes/ ? $Zugriffe + 1 : $Zugriffe;
}
if ($Zugriffe >= 1) #wenn es vorhanden ist
{
&Dead(); #dann verlasse den weiteren vorgang
}
else
{
close (DATEN);##hier ist das problem,wo ein zweiter zugriff der die daten wieder einliest,
den weiteren vorgang stören könnte bzw. die daten dann nochmals schreibt,
weil er in dem moment bevor er die daten schreibt ja schon einliest
und nicht weiss dass die daten bereits geschrieben wurden.##
Das verstehe ich nicht. du flockst doch oben deine Datei, also kann kein zweiter Vorghang die Datei lesen/schreiebn (LOCK_EX = exklusiv).
open(DATEN,">>$logfile") || &Dead('Cannot open file'); #ansonsten schreibe den text in die log
flock(DATEN,LOCK_EX);
print DATEN "$etwas_geschriebenes\n";
close (DATEN);
&email();
}
}
Wenn du allerdings meinst, dass das im gleichen Programm passiert, dann musst du die Datei immer zum lesen+schreiben öffnen.
Auch wenn's komplizierter ist, aber das ist CGI ;-)
Struppi.
hallo,
Ein Danke an Colocybe und struppi für die ausf. infos.
Sowas in der richtung "einmal lesen und schreiben alles in einem->schützen (flock)"
bis der vorgang komplett abgeschlossen ist,zu benutzen,wollte ich.
Ich hatte es versucht mit +> open aber ohne seek und truncate->(versteh ich nicht ganz)
dann wurde allerdings der ganze alte inhalt gelöscht,was nicht sein durfte.
Ausserdem möchte ich dass das zu schreibende nicht am anfang sondern
am schluss (ganz unten angehängt wird mit einem zeilen umbruch).
Wenn du allerdings meinst, dass das im gleichen Programm passiert, dann musst du die Datei immer zum lesen+schreiben öffnen.
ja so soll es sein
thx
Alain
bis der vorgang komplett abgeschlossen ist,zu benutzen,wollte ich.
Ich hatte es versucht mit +> open aber ohne seek und truncate->(versteh ich nicht ganz)
dann wurde allerdings der ganze alte inhalt gelöscht,was nicht sein durfte.
Ausserdem möchte ich dass das zu schreibende nicht am anfang sondern
am schluss (ganz unten angehängt wird mit einem zeilen umbruch).
Wenn du wirklich nur anhängen willst dann reicht seek und seek musst du immer benutzen wen du eine Datei mit +< öffnest, da du nicht sicher sein kannst, dass der Zeiger am Anfang der Datei steht.
Wenn du allerdings mittendrin was ändern willst, solltest du die Datei erst mit truncate (truncate schneidet ab der aktuellen Position die Datei ab) abschneiden und ab da neuschreiben.
Struppi.
hallo,
Danke,alles klar nun,
Wenn du wirklich nur anhängen willst dann reicht seek und seek musst du immer benutzen wen du eine Datei mit +< öffnest, da du nicht sicher sein kannst, dass der Zeiger am Anfang der Datei steht.
Wenn du allerdings mittendrin was ändern willst, solltest du die Datei erst mit truncate (truncate schneidet ab der aktuellen Position die Datei ab) abschneiden und ab da neuschreiben.
Dann werd ich es so mal versuchen.
Aber kannst du mir noch sagen was genau z.B. seek (FILE, 0, 2);
bedeutet ^ ?
grüsse vom
Alain
Dann werd ich es so mal versuchen.
Aber kannst du mir noch sagen was genau z.B. seek (FILE, 0, 2);
bedeutet ^ ?
hehe, dir hat noch keiner ein perldoc -f xxx entgegen geworfen?
Du findest die Dokumentation von Perl auf deiner Festplatte (zur Not auch im Internet http://perldoc.com/perl5.8.0/pod/func/seek.html) und die solltest du auch mal ausführlich studiert haben, da steht ein Haufen Wissen drin, der nützlich ist falls du dich länger mit Perl beschäftigen möchtest.
Struppi.
hallo,
hehe, dir hat noch keiner ein perldoc -f xxx entgegen geworfen?
doch auch schon :)
Also hier hab ich nun mein fertiges script das aber noch nicht richtig
zu funktionieren scheint bzw. nicht beendet wird und dadurch den inhalt
wieder löscht *nerv*
Hier ist das beispiel:
sub check
{
my $zugriff = 0;
open(DATEN,"+>$logfile") || die "cannot open $!\n";
flock(DATEN,LOCK_EX) || die "cannot lock $!\n";
while (<DATEN>){
/$etwas_geschriebenes/ ? $zugriff = $zugriff + 1 : $zugriff;
}
if ($zugriff >= 1)
{
&Dead(); #abruch
}
else
{
seek (DATEN, 0, 2);
print DATEN "$etwas_geschriebenes\n";
close (DATEN) || die "cannot close $!\n";
}
}
Was ist denn hier nun falsch?
Am Anfang steht dies
#!/usr/bin/perl -Tw
use CGI::Carp qw(fatalsToBrowser);
use Fcntl ':flock';
use strict;
aber ich bekomm auch keine error meldung mit use strict.
Gruss vom Alain
hi Alian
/$etwas_geschriebenes/ ? $zugriff = $zugriff + 1 : $zugriff;
in dieser zeile steckt dein fehler dein $zugriff wird nicht erhöht .!?
schreib das mal so $etwas_geschriebenes ? ($zugriff +=1) : ($zugriff);
oder so wie Struppi es in seinem posting geschrieben hat
bis bis roman
hallo roman,
/$etwas_geschriebenes/ ? $zugriff = $zugriff + 1 : $zugriff;
in dieser zeile steckt dein fehler dein $zugriff wird nicht erhöht .!?
doch es geht (war ja auch von selfhtml abgeschrieben) :)
die tips von struppi haben mir sehr viel weiter geholfen und dementsprechend
hab ich auch ein paar scripts nun umgeändert bis jetzt - und alle laufen jetzt,sogar mit
"#!/usr/bin/perl -Tw
use strict;"
es war die paar stunden arbeit wert.
so long
Alain
hehe, dir hat noch keiner ein perldoc -f xxx entgegen geworfen?
doch auch schon :)
aber nicht gelesen?
Also hier hab ich nun mein fertiges script das aber noch nicht richtig
zu funktionieren scheint bzw. nicht beendet wird und dadurch den inhalt
wieder löscht *nerv*
ist doch klar.
my $zugriff = 0;
open(DATEN,"+>$logfile") || die "cannot open $!\n";
Hier öffnest du die Datei zum lesen und schreiben und löscht sie gleichzeitig (der '>' operator löscht die Datei)
Du möchtest:
open DATEN, "+<$logfile" || die "cannot open $logfile: $!\n";
/$etwas_geschriebenes/ ? $zugriff = $zugriff + 1 : $zugriff;
Du brauchst hier kein if else Konstrukt, wie ich weiter oben schon schrub:
$zugriff++ if /$etwas_geschriebenes/;
}
if ($zugriff >= 1)
Da reicht dann:
if($zugriff)
{
&Dead(); #abruch
Das '&' Zeichen ist Perl4 Syntax und sollte nur eingestzt werden, wenn du weißt warum (du übergibst damit soweit ich weiß deiner Funktion @_)
}
else
{
seek (DATEN, 0, 2);
Da du mich ja schon nach der 2 gefragt hast, man sollte auch hier die Konstanten aus fnctl verwenden, da die 2 nicht immer SEEK_SET sein muss.
aber ich bekomm auch keine error meldung mit use strict.
Das ist ja schon mal gut ;-)
Struppi.
hallo struppi,
wieder löscht *nerv*
ist doch klar.
oh mann kann ich dumm sein *Kopfkratz->langsamAngstkrieg*
Du möchtest:
open DATEN, "+<$logfile" || die "cannot open $logfile: $!\n";
jetzt gehts so :)
sub check
{
my $zugriff = 0;
open(DATEN,"+<$logfile") || Dead();
flock(DATEN,LOCK_EX) || die "cannot lock $!\n";
while (<DATEN>){
$zugriff++ if /$etwas geschriebenes/;
}
if ($zugriff)
{
Dead();
}
seek (DATEN, 0, 2);
print DATEN "$etwas geschriebenes\n";
close (DATEN) || die "cannot close $!\n";
}
----------------
Ich dachte mir,man könnte z.B. das script direkt sterben lassen indem man z.B.
dies schreibt "dead() if /$etwas geschriebenes/;" anstatt $zugriff++ if...
aber das geht so nicht,ansosten könnte man dann auch auf den if zweig verzichten.
Da du mich ja schon nach der 2 gefragt hast, man sollte auch hier die Konstanten aus fnctl verwenden, da die 2 nicht immer SEEK_SET sein muss.
nach dem seek in form von fnctl habe ich nur http://www.perldoc.com/perl5.8.0/pod/func/seek.html etwas gesehen von
SEEK_END aber kein offizielles beispiel wie die form in seek(TEST,0,1); ?!
Müsste dies dann in etwa so seek(TEST,0,SEEK_END); aussehen?
Grüsse vom
Alain
jetzt gehts so :)
sub check
{
my $zugriff = 0;
open(DATEN,"+<$logfile") || Dead();
flock(DATEN,LOCK_EX) || die "cannot lock $!\n";
while (<DATEN>){
$zugriff++ if /$etwas geschriebenes/;
}
if ($zugriff)
{
Dead();
}
seek (DATEN, 0, 2);
print DATEN "$etwas geschriebenes\n";
close (DATEN) || die "cannot close $!\n";}
Ich dachte mir,man könnte z.B. das script direkt sterben lassen indem man z.B.
dies schreibt "dead() if /$etwas geschriebenes/;" anstatt $zugriff++ if...
aber das geht so nicht,ansosten könnte man dann auch auf den if zweig verzichten.
Stimmt, warum geht das nicht?
Dead() if /$etwas geschriebenes/;
sollte eigentlich funktionieren (wobei ich das Gefühl hab, dass sterben zuviel ist, oder?)
Da du mich ja schon nach der 2 gefragt hast, man sollte auch hier die Konstanten aus fnctl verwenden, da die 2 nicht immer SEEK_SET sein muss.
nach dem seek in form von fnctl habe ich nur http://www.perldoc.com/perl5.8.0/pod/func/seek.html etwas gesehen von
SEEK_END aber kein offizielles beispiel wie die form in seek(TEST,0,1); ?!
Müsste dies dann in etwa so seek(TEST,0,SEEK_END); aussehen?
oh, stimmt.
ich hatte mit den Konstanten auch einige Probleme, da die nicht überall laufen (also fcntl nicht immer exportiert). aber versuchen würd cih's auf jeden Fall:
use fcntl qw/:seek :flock/;
Struppi.
hallo struppi,
Stimmt, warum geht das nicht?
Dead() if /$etwas geschriebenes/;
sollte eigentlich funktionieren (wobei ich das Gefühl hab, dass sterben zuviel ist, oder?)
tatsächlich es geht,hatte gestern wohl eine { zuviel weggelassen.dead ist doch ein gutes wort
und trifft die funktion genau und so soll es auch sein :)
Müsste dies dann in etwa so seek(TEST,0,SEEK_END); aussehen?
oh, stimmt.
ich hatte mit den Konstanten auch einige Probleme, da die nicht überall laufen (also fcntl nicht immer exportiert). aber versuchen würd cih's auf jeden Fall:use fcntl qw/:seek :flock/;
denkst Du diese methode ist besser?Weil,wenn Du schon zweifelst an fcntl dann lass ich es lieber mal so wie's ist,denn es funtzt so tadelos.
Jedenfalls nochmals besten dank .
Grüsse
Alain
ich hatte mit den Konstanten auch einige Probleme, da die nicht überall laufen (also fcntl nicht immer exportiert). aber versuchen würd cih's auf jeden Fall:
use fcntl qw/:seek :flock/;
denkst Du diese methode ist besser?Weil,wenn Du schon zweifelst an fcntl dann lass ich es lieber mal so wie's ist,denn es funtzt so tadelos.
Jedenfalls nochmals besten dank .
ich hatte mal irgendwo eine veraltete Version von fcntl, das Problem mit den Werten ist, dass diese nicht auf allen Betriebsystemen gleich sein müssen. Während die Konstanten aus fcntl dem OS angepasst sind.
Struppi.
hi Struppi
/$etwas_geschriebenes/ ? $Zugriffe = $Zugriffe + 1 : $Zugriffe = $Zugriffe;
Das hatten wir doch letztens erst:
stimmt und zwar hier [pref:t=57918&m=326789] aber du willst ja nichts mehr lernen :-) *fg* (es kann ja nicht an gehen das ich immer nur von dir lerne)
Besser so:
$Zugriffe = /$etwas_geschriebenes/ ? $Zugriffe + 1 : $Zugriffe;
tztz
$etwas_geschriebenes ? ($Zugriffe += 1) : ($Zugriffe);
bis bis roman
Das hatten wir doch letztens erst:
stimmt und zwar hier [pref:t=57918&m=326789] aber du willst ja nichts mehr lernen :-) *fg* (es kann ja nicht an gehen das ich immer nur von dir lerne)
Besser so:$Zugriffe = /$etwas_geschriebenes/ ? $Zugriffe + 1 : $Zugriffe;
tztz$etwas_geschriebenes ? ($Zugriffe += 1) : ($Zugriffe);
Hier ist dieser Operator überflüssig.
noch einfacher, da er ja bei else eh nichts machen will:
$Zugriffe++ if /$etwas_geschriebenes/;
Struppi.