Thread Wachsenden Dateien folgen: tail -f (33 answers)
Opened by sid burn at 2006-10-06 00:49

sid burn
 2006-10-06 00:49
#70512 #70512
User since
2006-03-29
1520 Artikel
BenutzerIn

user image
Tag zusammen,
eins vorweg, ich Interessiere mich gerade eher darum ob dies überhaupt machbar ist, und wenn ja wie. Ich habe dafür aber zur Zeit keinen Verwendungszweck, daher kommt es mir jetzt nicht darauf an wieviel Sinn es nun macht soetwas zu Implementieren.

Was ich Wissen würde ist wie man mit "rohen" Perl schafft eine Datei zu Verfolgen. Eine Datei Zeilenweise zu Verfolgen und diese Auszugeben habe ich geschafft und war auch nicht so schwer. Zum anderen gab es dazu ja auch ein Eintrag im perlfaq. Allerdings ist es noch nicht das was "tail -f" macht.

Den Code der dort steht habe ich verändert, zum einen sysread und syswrite genommen. Vor allem syswrite() damit auch Zeilen ausgegeben werden die nicht auf ein Newline Enden. Oder eben nur um Zeichen erweitert werden, und die Zeile noch nicht abgeschlossen ist.

Zusätzlich gibt mir "tail -f" aber immer noch die Daten sofort aus, die ich an einer Datei anhänge. Während man bei der bekannten Methode in perlfaq sein Skript mit "sleep 1" üblicherweise 1 Sekunde warten lässt.

Genau das möchte ich noch vermeiden.

Ich hatte zuerst an select() gedacht, so dass ich erst alles vom Filehandle Lese, und danach solange warte bis auf dem Filehandle wieder etwas zu Lesen vorhanden ist. Da mir select() zu kompliziert ist habe ich IO::Select genommen.

Code: (dl )
1
2
3
4
5
6
7
8
9
10
11
12
use IO::Select;

open my $file, '<', 'tail' or die $!;
my $select = IO::Select->new( $file );
while (my @ready = $select->can_read ) {
for my $fh (@ready) {
while ( sysread $fh, my $buff, 100 ) {
syswrite STDOUT, $buff;
}
}
}
close $file;

Zwar Funktioniert das ganze wie erwartet. Allerdings nur auf den ersten Blick. Fügt man ein "syswrite STDOUT, 'a'" in der for Schleife hinzu, direkt vor der while Schleife wird man sehen das dies eine Endlosschleife ist die durchgängig ohne Pause ausgeführt wird.

"top" zeigt dann auch 100% Prozesserauslastung an. Und jetzt meine Frage, warum blockt die Methode "can_read" nicht wie sie sollte?

Zur Zeit ist der Code eher identisch mit
Code: (dl )
1
2
3
4
5
6
7
open my $file, '<', 'tail'  or  die $!;
while (1) {
while ( sysread $file, my $buff, 100 ) {
syswrite STDOUT, $buff;
}
}
close $file;



Gibt es also eine Möglichkeit irgendwie solange zu Blocken bis neue Daten auf ein Filehandle vorhanden sind, und dann erst etwas zu tun? IO::Select funktioniert hier anscheind nicht. Ist wohl eher für Handles gedacht die sich danach Leeren (Sockets), und nicht für Dateihandles.


Noch Interessanter wäre sogar wenn irgendwie ein Event gesendet wird, dass man dann flexibel Abfragen könnte, und nebenbei dann etwas anderes machen kann. Ich glaube aber ohne fork() oder Threads sollte dies wohl unmöglich sein?


Eine andere Frage, warum wird in der FAQ eigentlich gesagt das man clearerr() oder seek() aufrufen soll um das EOF zu Löschen? Bei mir Funktioniert es auch ohne, und auch wenn ich es benutze macht es bei mir keinen Unterschied.


Klar, ich könnte anstatt (sleep 1) auch ein "select( undef, undef, undef, 0.1) nehmen, dann sieht es auch aus, als wenn die Einträge "sofort" erscheinen, und ich habe keine 100% Prozessorauslast, allerdings ist das nicht wirklich die Lösung des Problems, sondern wohl eher nur ein Workaround.


Zu den Modulen:
Habe mir File::Tail angeschaut letztendlich funktioniert es anscheind auch nur so das es "sleep" aufruft.\n\n

<!--EDIT|sid burn|1160081851-->
Nicht mehr aktiv. Bei Kontakt: ICQ: 404181669 E-Mail: perl@david-raab.de

View full thread Wachsenden Dateien folgen: tail -f