mehrere Dateien überwachen
|
Seitenanfang |
| Hallo, ich hab folgende Situtaion: ich hab mehrere Dateien (TEXT) in die von unterschiedlichen Programmen geschrieben wird. (linuxrechner) Ich bräuchte ein Programm dem ich bei Start eine Liste der Dateien übergebe, und dass ab dann alle Inhaltsänderungen überwacht und ausgibt (oder anders weiterverarbeitet). Für eine einzelne Datei ist das kein Problem, was mir Probleme macht, ist das ich vorher nie weis wieviele Dateien ich überwachen muss, und das gleichzeitige lesen aus mehreren Dateien. Ich finde nicht den richtigen Ansatz, hat jemand einen Tipp für mich? Grüsse devnull
Datum: 11.05.2005-13:30

|
re: mehrere Dateien überwachen
|
Seitenanfang |
| vielleicht ist fork ein Ansatz... Für jede Datei ein Child erzeugen... http://wiki.perl-community.de/bin/view/Wissensbasis/AllgemeinesFork
Datum: 11.05.2005-14:19

|
re: mehrere Dateien überwachen
|
Seitenanfang |
Hab ich auch drann gedacht will ich aber nur machen wenn nicht anders möglich. Gibt es vieleicht ne Möglichkeit mit IO::Handle oder IO::File?
Datum: 11.05.2005-15:24

|
re: mehrere Dateien überwachen
|
Seitenanfang |
use IO::Select ;-) use IO::Select;my $s = IO::Select->new(); $s->add(\*HANDLE); # HANDLE zum Überwachen eintragen while(1) { # Hauptschleife foreach my $f ($s->can_read(0.001)) { # can_read gibt die Liste der "lesbaren" Handles aus my $daten=<$f>; # daten lesen } }
Hoffe geholfen zu haben...
Datum: 15.05.2005-02:13

|
re: mehrere Dateien überwachen
|
Seitenanfang |
| Ja danke funktioniert sehr gut, lediglich die CPU Last geht auf 100% während das Programm ausgeführt wird. Hat jemand eine Idee wie ich damit umgehen kann? Sprich kann ich irgendwie verhindern das die Endlosschleife meine gesammte CPU auslastet ? Grüsse
Datum: 18.05.2005-11:45

|
re: mehrere Dateien überwachen
|
Seitenanfang |
Oops, das hatte ich vergessen: die 0.001 bei $s->can_read(0.001) ist der timeout des poll. wenn der höher gestellt wird, wird die cpulast geringer.Allgemein, zum select()-syscall: der call kommt bei zwei möglichen ereignissen zurück: entweder, wenn eines der zu überwachenden Handles einen event feuert (also les- oder schreibbar wird) oder wenn die als timeout gesetzte zeitspanne abgelaufen ist. ein Timeoutparameter 'undef' bewirkt ewiges Warten... man IO::Select verrät den Rest.
Datum: 18.05.2005-16:55

|
re: mehrere Dateien überwachen
|
Seitenanfang |
| Hab ne andere Lösung für das Last-problem gefunden Ich hab einfach den nice Wert mit den Systemaufruf 'renice' auf Maximum gesetzt. Mein Prozess verursacht jetzt zwar immer noch 95% Cpu Last aber er gibt sofort an andere Prozesse ab da er mit niedriger Priorität läuft. Damit kann ich leben. Danke für di Hilfe
Datum: 20.05.2005-09:02

|
re: mehrere Dateien überwachen
|
Seitenanfang |
Autsch! So war das nicht gedacht!Der Select-Call muss überhaupt keine Rechenzeit verbrauchen; der Timeout ist nur dazu da, während des Wartens in regelmässigen Abständen noch andere sinnvolle Dinge tun zu können, z.B. die Uhrzeit oder "warte immer noch..." oder auch "Immer noch nichts Neues von den verschwundenen Delphinen" auf den Screen zu pinseln. Auch wenn der Zeitwert auf 'undef' steht, kommt der Select-Call zuverlässig zurück, sobald einer der Deskriptoren seinen Zustand ändert. Bitte immer auch an den Energieverbrauch / die Abwärmeproblematik denken! Ein Zeitwert von 'undef' schont die Kohlevorkommen und entlastet die Klimaanlage. Wir steuern sowieso alle auf den Wärmetod zu :-) (früher oder später :-) Gruss Olaf der Sparsame.
Datum: 20.05.2005-16:33

|
re: mehrere Dateien überwachen
|
Seitenanfang |
| @obulon Hi, war leider ne Weile mit was anderem beschäftigt... ich komm nicht ganz dahinter was du meinst. Ich muß doch immer in einer Schleife (endlos) alle verfügbaren Handel überprüfen. Hier z.b: while (@ready = $s->can_read) { foreach my $f (@ready) { my $daten=<$f>; if (defined ($daten)){ #tue irgendwas mit daten... } } } und eben diese Schleife verursacht eine hohe Cpu-Last. Ich sollte noch erwähnen dass ich das Prog als Daemon laufen habe. Gruß devnull der unter den Daemonen leidet die er rief
Datum: 30.05.2005-13:05

|
re: mehrere Dateien überwachen
|
Seitenanfang |
@ready = $s->can_read(timeout) gibt ein array zurück. in diesem Array stehen alle lesbar gewordenen Deskriptoren. Wenn das Array leer ist, dauert der Call 'can_read' exakt 'timeout' Sekunden. Im Klartext heisst das: liefere mir eine Liste mit allen lesbaren Handles, aber warte auf das Lesbarwerden maximal 'timeout' Sekunden.Die Schleife wird also maximal alle 'timeout' Sekunden durchlaufen. Wenn der Timeout 0 ist, wird die Schleife eben OHNE Wartepause durchlaufen. Dementsprechend hoch ist dann die Last. Vielleicht hilft folgende Analogie: Gibt es lesbare Handles? Wenn ja, gib Liste der Handles zurück. Wenn nein, schlafe 'timeout' Sekunden. zu den Timeoutwerten: ein Timeout von '3' schläft also 3 Sekunden. ein Timeout von '0' schläft also 0 Sekunden. ein Timeout von 'undef' schläft ewig. Ich hoffe, so wars klar genug. Gruss Olaf
Datum: 30.05.2005-13:22

|
re: mehrere Dateien überwachen
|
Seitenanfang |
Ja danke, hatte doch richtig verstanden. Aber egal wie hoch ich den Timeout einstelle (auch undef), der Prozess belegt immer die meiste Rechenzeit.Die Systemlast zeigt sich aber (dank hohem nice Wert) ziemlich unbeeindruckt. Da ich gedenke das Progrämmelchen auf Servern einzusetzen die auch sehr hohe System-(lasten) vertragen hab ich da wenig bedenken. Mich stört nur das in der Prozessliste das Teilchen immer auf Platz 1 liegt :) Gruß devnull
Datum: 30.05.2005-14:03

|
re: mehrere Dateien überwachen
|
Seitenanfang |
poste bitte nochmal das ganze script. irgendwas stimmt da nicht...
Datum: 30.05.2005-16:32

|
re: mehrere Dateien überwachen
|
Seitenanfang |
Es handelt sich erst mal um einen prinzipiellen Test ohne irgendwelche Fehlerbehandlung, aber vieleicht hab ich ja wirklich den fehler an einer anderen Stelle. #!/usr/bin/perl -w #use strict; use POSIX; use Sys::Syslog; use Net::Syslog; use IO::Select; use IO::File; $0='logfeedd'; my $time_to_die =0; my $line; my $rootdir='/var/logfeedd'; my $config='/etc/logfeedd.conf'; my @logfiles; my $logfile; my $i=0; my @ready;print "Mypid= $$\n"; sleep 2; `renice +20 -p $$`; my $pid =fork; exit if $pid; die "Fehler bei fork: $!" unless defined ($pid); POSIX::setsid() or die "Konnte keine neue Session starten: $!"; print "Childpid = $$\n"; my $log=new Net::Syslog(Facility=>'local1'); open CONF, $config or die "Konnte $config nicht öffnen\n$!"; while ($line=<CONF>){ push @logfiles,$line; print "Datei: $line\n"; } close CONF; sub signal_handler { print "Beendet:\n"; $time_to_die =1; } $SIG{INT} = $SIG{TERM} = $SIG{HUP} = \&signal_handler; my $fh; my $s= IO::Select->new(); foreach $logfile (@logfiles){ $i=$i+1; $fh="DAT$i"; print "$fh.\n"; open $fh, $logfile; $s->add(\*$fh); print $logfile; } do{ @ready = $s->can_read(undef); foreach my $f (@ready) { my $daten=<$f>; if (defined ($daten)){ print $daten; #$log->send($daten,Priority=>'info',SyslogHost=>'10.1.4.20',SyslogPort=>'5140'); } } } until ($time_to_die);
Datum: 31.05.2005-09:03

|