Forum: PC-Programmierung Perl Datei auf Netzlaufwerk kopieren - Datei zu lange blockiert


von perlzulangsamNEoda (Gast)


Lesenswert?

Hallo Communty,

ich habe ein sehr kurioses Problem.

Folgenden Code verwende ich:
1
#TempFile schreiben
2
my $TempFile = "/tmp/test.csv";
3
my $OutPutFile = "/mnt/TestLaufwerk/output.csv";
4
5
open(DATEI, "> $TempFile") or die "Fehler beim Schreiben der Datei $!";
6
print DATEI "CMDBID;Computername\r\n";
7
foreach(@ExportListe)
8
{
9
        print DATEI "$_\r\n";
10
}
11
close(DATEI) or die "Fehler beim Schließen $!";
12
13
#copy($TempFile, $OutPutFile) or die "Fehler beim kopieren auf Snowserver";
14
exec("mv $TempFile $OutPutFile");
15
#unlink($TempFile) or die $!; # Tempfile wieder löschen

Auf der Netzlaufwerkseite läuft ein eventbasiertes Programm, welches 
reagiert sobald dort eine neue Datei abgelegt wurde.
Diese Datei wird dann sofort geöffnet und weiterverarbeitet.

Wenn ich diese Datei mittels meinem Script ablege, bekomme ich den 
Fehler auf der eventbasierten Seite - "Datei wird von einem anderem 
Prozess genutzt und kann nicht geöffnet werden"

Wenn ich die Datei in der Console mittels "cp datei1 datei2" Befehl aus 
dem Tempordner manuell kopiere, funktioniert alles ohne Probleme.

Ist das PERL Script vielleicht wirklich einfach zu langsam? Hat hier 
irgendjemand eine Idee?

Den Fehler erhalte ich wenn ich die Copy Funktion aus File::Copy 
benutze, bei exec() und bei system();

Ich bin ratlos, danke für euere Hilfe im Voraus!

von Planlos (Gast)


Lesenswert?

perlzulangsamNEoda schrieb:
> Ich bin ratlos, danke für euere Hilfe im Voraus!

Erst kopieren, dann umbenennen.

Also zuerst ein copy auf "$netzwerk/$filename.tmp", dann ein rename 
"$netzwerk/$filename.tmp"-> "$netzwerk/$filename"

von perlzulangsamNEoda (Gast)


Lesenswert?

Planlos schrieb:
> perlzulangsamNEoda schrieb:
>> Ich bin ratlos, danke für euere Hilfe im Voraus!
>
> Erst kopieren, dann umbenennen.
>
> Also zuerst ein copy auf "$netzwerk/$filename.tmp", dann ein rename
> "$netzwerk/$filename.tmp"-> "$netzwerk/$filename"

Hat leider ebenfalls nicht funktioniert. Dann meckert die Serverseite, 
dass er die Datei nicht finden kann und fasst sie gar nicht mehr an.

Auf das MoveEreignis greift die Serverseite wohl nicht zu...


Hat noch jemand eine andere Idee?

von Planlos (Gast)


Lesenswert?

Aus perl heraus mit system('/bin/cp',$tempfile,$serverfile);
umkopieren.

'/bin/cp' implementiert für einige (Netzwerk-)Dateisysteme 
Sonderbehandlungen, mappt die Kopieraktion auf spezielle Syscalls.

Dein Perl-Programm mit 08/15 Standard-read&write-Syscalls kann da nicht 
mithalten.

Eigentlich ist das Server-Programm fehlerhaft, wenn es sich auf solche 
Nebenbedingungen verlässt.
Wenn du aber am Server nichts ändern kannst, muss halt ein Würg-Around 
am Client her.

von Ralf D. (doeblitz)


Lesenswert?

perlzulangsamNEoda schrieb:
[...]
> Auf der Netzlaufwerkseite läuft ein eventbasiertes Programm, welches
> reagiert sobald dort eine neue Datei abgelegt wurde.
> Diese Datei wird dann sofort geöffnet und weiterverarbeitet.

Das ist ein Designfehler auf einer der beiden Seiten. :-(

Entweder du mußt deine Daten auf dem Netzlaufwerk erzeugen und dann nach 
Abschluß des gesamten Schreibvorgangs dort in das Zielverzeichnis 
verschieben (auf dem gleichen Filesystem, so daß das eine atomare 
Operation ist) oder das Serverprogramm muß alternativ nicht auf das 
Auftauchen der Datei reagieren, sondern auf das Schließen der neu 
aufgetauchten Datei (unter Linux: man 7 inotify, speziell 
IN_CLOSE_WRITE), so daß die Dauer des Schreibvorgangs irrelevant wird.

> Wenn ich diese Datei mittels meinem Script ablege, bekomme ich den
> Fehler auf der eventbasierten Seite - "Datei wird von einem anderem
> Prozess genutzt und kann nicht geöffnet werden"

Wie erwartet, der Versuch der Verabeitung erfolgt bereits während die 
Datei noch geschrieben wird statt erst nach Abschluß des 
Schreibvorgangs.

> Wenn ich die Datei in der Console mittels "cp datei1 datei2" Befehl aus
> dem Tempordner manuell kopiere, funktioniert alles ohne Probleme.

Zufall - auch da kannst du mal Pech haben, auch wenn es wegen der 
höheren Geschwindigkeit unwahrscheinlicher wird.

> Ist das PERL Script vielleicht wirklich einfach zu langsam? Hat hier
> irgendjemand eine Idee?

Entweder auf Serverseite die Event-Überwachung korrigieren (inotify) 
oder aber das klassische create/rename-Konzept anwenden (wie oben 
beschrieben).

von Irgendwer (Gast)


Lesenswert?

perlzulangsamNEoda schrieb:
> Auf der Netzlaufwerkseite läuft ein eventbasiertes Programm, welches
> reagiert sobald dort eine neue Datei abgelegt wurde.
> Diese Datei wird dann sofort geöffnet und weiterverarbeitet.

Der event wird meistens schon ausgelöst wenn die Datei angelegt wurde 
aber die eigentliche Dateiübertragung noch am laufen ist.
Von daher erstmal eine Zeitlang die Dateigröße beobachten und erst wenn 
die sich eine gewisse Zeit nicht mehr verändert die Datei öffnen.

von Der Andere (Gast)


Lesenswert?

Irgendwer schrieb:
> Von daher erstmal eine Zeitlang die Dateigröße beobachten und erst wenn
> die sich eine gewisse Zeit nicht mehr verändert die Datei öffnen.

So ist es, das serverseitige Programm ist Murks. Es darf eine Datei erst 
dann aufmachen wenn sie nicht mehr vom schreibenden System in Benutzung 
ist.

Wenn man das Programm nicht ändern kann sollte der Vorschlag von Planlos 
noch am besten ein.

von Der Andere (Gast)


Lesenswert?

Ralf D. schrieb:
> Wie erwartet, der Versuch der Verabeitung erfolgt bereits während die
> Datei noch geschrieben wird statt erst nach Abschluß des
> Schreibvorgangs.

Selbst das könnte funktionieren, wenn die Datei shared als Stream 
geöffnet wird und das read entsprechend wartet, bzw man wie bei TCP/IP 
Sockets programmiert, dass man evt. mehrfach lesen muss um alle Daten zu 
erhalten.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.