Schreibzugriff auf bestimmte Datei filtern oder mitschneiden
-
Hallo,
welche Möglichkeiten gibt es denn so unter GNU/Linux, die Schreibzugriffe in eine bestimmte Datei mitzuverfolgen oder zu filtern?
Problem: Ein Programm (Blackbox) schreibt ständig (exklusiv) Protokolldaten in eine Datei. Leider nicht auf StdOut, was man ja schön pipen könnte.
Diese Daten sind sehr nützlich, aber leider auch sehr umfangreich.
Zu beliebigen Zeitpunkten sollen die Information abgefragt werden. Bisher mache ich es so, dass die Datei gelesen wird und zeilenweise nach den interessierenden Daten gesucht wird. Nicht besonders performant, da weniger als 1% davon relevant ist.
Ich hätte daher gerne ein Filter dazwischen geschaltet.Ist das irgendwie im Userspace machbar?
Ein virtuelles File klingt sehr vielversprechend http://lwn.net/Articles/57369/ aber ist wohl leider nur als Kernelmodul zu realisieren.
-
Na gut, dann werde ich es eben über FUSE machen.
-
Kannst du nicht einfach die Logdatei durch ein FIFO ersetzen und dann innerhalb deines Programmes abfragen?
-
Das klingt nach einer sehr guten Idee, das werde ich definitiv ausprobieren.
-
Das klappt wirklich
Eine Frage noch zu den FIFOs: Wenn das Programm da rein schreibt, aber noch kein Empfänger da ist, dann gehen die Daten in der Linux-Implementierung ja nicht verloren. Wenn dann ein anderes Programm, z.B. cat, den Pipe ausliest, dann erhält er alles, was bis dahin noch nicht gelesen wurde.
Wo bzw. wer speichert das zwischen? Ist es in Ordnung, wenn in das Pipe ein paar zig MB geschrieben werden, bevor gelesen wird oder verkleistert das irgendwann den Ausgabepuffer von dem ganzem Programm oder so?
-
Kurze (vielleicht dumme) Zwischenfrage:
Wie sieht die Kommunikation nun aus?
Um mit FIFOs zu arbeiten musst du beide Programme anpassen?
Also es gibt keine Möglichkeit die Ausgabe in die Datei von einem anderen Programm abzufangen bzw. umzuleiten...?
Dazu benutzt du pipe (http://opengroup.org/onlinepubs/007908775/xsh/pipe.html), oder?Würde mich interessieren
-
Hallo,
also anpassen kann ich den Datenerzeuger gar nicht, da glorreiches Closed-source
Soviel ich bis jetzt sagen kann, klappt mit der named-pipe aber alles soweit, dass das Programm da rein schreibt und das Betriebssystem zwischenspeichert, falls noch kein "Ableser" da ist. (Ich bin nur nicht sicher, ob die Pipe irgendwann platzt, wenn man immer nur reinschreibt ohne was rauszulesen
)
Jedenfalls werde ich jetzt einen kleinen Daemon schreiben, der stets versucht, neue Zeilen aus der FIFO zu lesen. Wenn keine neuen Daten mehr da sind (die Pipe also leer ist), dann wird ja automatisch geblockt, der Daemon also "schlafen gelegt". Sobald neue Daten in die FIFO geschrieben werden, sollte ja Linux den Daemon automatisch aufwecken und er liest dann die neuen Daten ein.
Der Daemon parst die Zeilen dann nach interessanten Informationen, der Rest wird einfach verworfen. Mein Programm kann dann also mit meinem Daemon über eine wohldefinierte Schnittstelle die Infos effizient abfragen.
PS: Vermutlich integriere ich aber den Daemon gleich in das Programm.
PPS: Der Pipe-Syscall ist, glaub ich, nur für Interprozesskommunication, wenn beide Prozesse mitspielen. (Also anonyme Pipes).
Ich werde einfach mit dem Userprogramm mkfifo ein FIFO im Filesystem erstellen und der Daemon liest es ganz normal über fopen aus. Aus Programmsicht handelt es sich ja um eine ganz normale Datei, die eben manchmal auch blockt.
-
Also bin mir nicht sicher, ob ichs verstanden hab:
Dein Closed-Source Programm schreibt ein Log in z.B. "programm.log".
Bevor du das Closed-Source Programm startest, wird dein Programm (MyProgramm) angeworfen.
MyProgramm erzeugt eine FIFO mkfifo("programm.log",mode) und liest anschliessend von der FIFO-Datei.
Wird nun Closed-Source gestartet bekommt MyProgramm die Ausgaben mit.Stimmt das so?
Interessiert mich, weil es für mich einen ähnlichen Anwendungsfall geben könnte.
-
ihoernchen schrieb:
Dein Closed-Source Programm schreibt ein Log in z.B. "programm.log".
Korrekt.
ihoernchen schrieb:
Bevor du das Closed-Source Programm startest, wird dein Programm (MyProgramm) angeworfen.
Jein. MyProgram kann zu jeder beliebigen Zeit gestartet werden. (Hoffe ich.)
Wird es vorher gestartet, so gibt es eben noch nix zum lesen und es legt sich schlafen, bis von Linux das entsprechende SIGNAL kommt, dass es was zum lesen gibt. (Das sollte alles das OS für uns erledigen, aus Programmierersicht wird einfach nur fopen und dann read ausgeführt.)MyProgram kann aber auch später erst gestartet werden. Dann hat es natürlich erstmal gut zu tun, da unter Umständen das Log natürlich schon prall gefüllt ist. (So wie bei dem Film "Bruce allmächtig gestern, wo er die E-Mails abgefragt hat und er 3.5 Millionen Gebete abarbeiten musste.)
ihoernchen schrieb:
MyProgramm erzeugt eine FIFO mkfifo("programm.log",mode) und liest anschliessend von der FIFO-Datei.
Nein, in meinem Fall erstelle ich mir lieber vorher eine statische FIFO in der Shell mit dem Befehl mkfifo. (Wie im englischen Wikieintrag über FIFOs.)
Daher wird nichts zerbrechen, wenn nur eine von beiden Programmen Dienst schiebt. Linux speichert alles zwischen. Nur, dass das geschriebene verloren geht, wenn PropriAppbeendet wird, bevor MyProgram gestartet wird und alles liest.
Das ist in meinem Fall aber sogar wünschenswert.
-
Eine kleine Nachkorrektur:
Das Betriebssystem scheint auch beim Schreibzugang zu blocken, solange keiner aus der Pipe liest. Das macht es natürlich quasi obligatorisch, MyProgram vorher zu starten, damit die Closes-Source App nicht womöglich festhängt.
Du kannst es selbst ausprobieren, wenn das Programm hw ein HelloWorld Programm ist:
Terminal 1:
~$ mkfifo myfifo ~$ ./hw Hello, world! ~$ ./hw > myfifo
Programm hängt fest beim Schreibzugriff auf StdOut
Terminal 2:
~$ cat myfifo Hello, world!
hw ist jetzt fertig, denn es konnte die Welt begrüßen.