Frage Logge dich durch einen FIFO, dann umleiten zu einer Datei?


Ich habe eine Anwendung, die jede Transaktion protokollieren muss. Jede Protokollnachricht wird gelöscht, weil wir eine Aufzeichnung dessen haben müssen, was zu einem Absturz geführt hat. Meine Kollegen und ich waren neugierig, wie wir die Leistungseffekte der Pufferung erzielen und gleichzeitig sicherstellen konnten, dass die Protokollnachricht den Prozess verlassen hat.

Was wir uns ausgedacht haben, ist:

  • Machen Sie einen FIFO, auf den die Anwendung schreiben kann, und
  • Leiten Sie den Inhalt dieses FIFO über eine Datei in eine normale Datei um cat.

Das heißt, was war normalerweise:

app --logfile logfile.txt

ist jetzt:

mkfifo logfifo
cat logfifo &> logfile.txt &
app --logfile logfifo

Gibt es irgendwelche Probleme mit diesem Ansatz? Es hat funktioniert, als wir es getestet haben, aber wir möchten absolut sicher gehen, dass die Nachrichten ihren Weg zur Redirect-Datei finden, selbst wenn die ursprüngliche Anwendung abstürzt.

(Wir haben nicht den Quellcode zur Anwendung, so dass Programmierlösungen nicht in Frage kommen. Die Anwendung schreibt auch nicht stdoutEs ist also nicht möglich, direkt zu einem anderen Befehl zu gelangen. So syslog ist keine Möglichkeit.)


Aktualisieren: Ich habe ein Kopfgeld hinzugefügt. Die angenommene Antwort wird nicht umfassen logger aus dem einfachen Grund, dass logger ist nicht wonach ich gefragt habe. Wie die ursprüngliche Frage besagt, suche ich nur nach Fehlern bei der Verwendung eines FIFO.


8
2018-02-15 20:23


Ursprung


In einigen der bisherigen Antworten scheint eine immense Verwirrung zu herrschen. Wie ich ursprünglich in meiner Frage hervorgehoben habe, suche ich Probleme mit dem Ansatz, einen FIFO als Logging-Vermittler zu verwenden. Ich bin nicht an alternativen Vorschlägen interessiert, die nicht zumindest die Gotchas meiner ursprünglichen Frage. - chrisaycock
Wenn meine Antwort über das Protokollieren auf stdout keine Richtung ist, die Sie interessiert, könnten Sie vielleicht entfernen "Auch die Anwendung wird nicht auf stdout schreiben, so dass die direkte Verbindung zu einem anderen Befehl nicht in Frage kommt"? - nickgrim


Antworten:


Beachten Sie, dass in der Regel ein Fifo für die Programmierung erforderlich ist, bei dem die eingegebene Menge die ausgelesene Menge übersteigen kann.

So wie ein Fifo wird nicht ganz reibungslos funktionieren, wie Sie erwarten, aber würde Ihr Hauptproblem lösen, während Sie ein anderes einführen.

Es gibt drei mögliche Vorbehalte.

  1. Das Schreiben in den FIFO ist auf unbestimmte Zeit blockiert, wenn bei der Initialisierung nichts das andere Ende liest.
  2. Der Fifo hat eine feste Breite von 64K, durch die, wenn der Puffer an diesem Punkt gefüllt ist, weitere Schreibvorgänge blockiert werden, bis der Leser aufgeholt hat.
  3. Der Rohrschreiber wird mit SIGPIPE getötet, wenn der Leser stirbt oder austritt.

Dies bedeutet, dass Ihr Problem (Emulation gepufferter E / A bei einem nicht gepufferten Schreibvorgang) behoben wird. Das ist so, weil das neue 'Limit' in Ihrem FIFO tatsächlich die Geschwindigkeit dessen wird, was das Dienstprogramm schreibt, was sich in der Pipe auf der Platte befindet (was vermutlich gepufferte E / A sein wird).

Dennoch wird der Schreiber abhängig von Ihrem Log-Reader, um zu funktionieren. Wenn der Leser plötzlich aufhört zu lesen, wird der Schreiber blockieren. Wenn der Reader plötzlich beendet wird (sagen wir, Sie haben keinen Speicherplatz mehr auf Ihrem Ziel), wird der Brenner SIGPIPE und wahrscheinlich auch beenden.

Ein weiterer Punkt ist, wenn der Server in Panik gerät und der Kernel nicht mehr reagiert, können Sie bis zu 64.000 Daten verlieren, die sich in diesem Puffer befanden.

Eine andere Möglichkeit, dies zu beheben, besteht darin, Protokolle in tmpfs (/ dev / shm unter linux) zu schreiben und die Ausgabe an einen festen Speicherort auf der Festplatte zu setzen. Es gibt weniger restriktive Grenzen für die Speicherzuweisung (nicht 64K, normalerweise 2G!), Aber möglicherweise nicht für Sie, wenn der Writer keine dynamische Möglichkeit hat, Log-Dateien erneut zu öffnen (Sie müssten die Logs regelmäßig aus tmpfs löschen). Wenn der Server in dieser Methode in Panik gerät, könnten Sie viel mehr Daten verlieren.


5
2018-02-23 15:43



Das sind einige gute Informationen bezüglich /dev/shm. Das hatten wir auch in Betracht gezogen, obwohl es mir entfallen war tail -f. - chrisaycock


mkfifo logfifo
cat logfifo &> logfile.txt &
app --logfile logfifo

Was passiert, wenn Sie? cat logfifo Prozess stirbt, jemand tötet es durch Zufall, oder jemand zeigt es versehentlich an den falschen Ort?

Meine Erfahrung ist, dass die app wird schnell blocken und hängen. Ich habe das mit Tomcat, Apache und ein paar kleinen, selbst entwickelten Anwendungen ausprobiert und stieß auf das gleiche Problem. Ich habe nie sehr weit geforscht, weil logger oder einfache I / O-Umleitung hat getan, was ich will. Normalerweise benötige ich die Logging-Vollständigkeit nicht, was Sie versuchen zu verfolgen. Und wie Sie sagen, Sie wollen nicht Logger.

Es gibt eine Diskussion über dieses Problem bei Nicht blockierendes Linux-Fifo (On-Demand-Protokollierung).


4
2018-02-22 00:35



Interessant. Also könnte die App trotzdem blocken? Wir denken daran, das Handtuch zu werfen und Fusion IO an dieser Stelle zu bestellen. - chrisaycock
Versuche es. Dieses Ergebnis ist für mich schnell (in einer Testumgebung auf niedriger Hardware). Dies war auf Ubuntu und RedHat 5. Nicht sicher, ob FreeBSD, etc. ähnliches Verhalten haben. - Stefan Lasiewski


Ihre Optionen sind durch die App ziemlich begrenzt, aber was Sie getestet haben, wird funktionieren.

Wir machen etwas ähnliches mit Lack und Lackncsa, um die Protokolle für uns nützlich zu bekommen. Wir haben ein Fifo und lesen es einfach mit syslog-ng und senden es dort, wo wir es brauchen. Wir verarbeiten etwa 50 GB und haben bisher noch kein Problem mit diesem Ansatz


2
2018-02-15 21:24



Cool, froh zu hören, dass wir nicht die Einzigen sind. - chrisaycock


Die Umgebung ist CentOS und die Anwendung schreibt in eine Datei ...

Anstatt eine normale Datei zu senden, würde ich die Ausgabe an syslog senden und sicherstellen, dass Syslog-Nachrichten sowohl an einen zentralen Server als auch lokal gesendet werden.

Sie sollten in der Lage sein, ein Shell-Skript wie folgt zu verwenden:

logger -p daemon.notice -t app < fifo

Du könntest auch Eingaben machen (to logger) von cat oder von tail -f in eine Pfeife:

tail -f fifo | logger ...
cat fifo | logger ...

Das einzige Problem ist, dass es nicht basierend auf der Wichtigkeit der Protokollnachricht differenziert (alles ist BEACHTEN) aber es wird zumindest protokolliert und auch von einem Host auf einen zentralen Server gesendet.

Die Konfiguration von Syslog hängt davon ab, welchen Server Sie verwenden. Es gibt rsyslog und syslog-ng (beide sehr fähig).

BEARBEITEN: Überarbeitet, nachdem mehr Informationen vom Poster erhalten wurden.


2
2018-02-15 20:29



Die Protokollnachrichten werden in eine Datei geschrieben, die wir auswählen können, aber die Anwendung schreibt nicht stdout. Das Betriebssystem ist CentOS (Ich hatte die Frage als markiert Linux, aber ich denke, das ist leicht zu übersehen). Alle Nachrichten sind gleich wichtig, daher besteht in dieser Anwendung kein Unterschied zwischen einem Hinweis und einem Fehler. - chrisaycock
Kein Unterschied zwischen einem Hinweis und einem Fehler? Oh Ja wirklich? Kein Unterschied zwischen Slow query detected und Database halted? - Mei
(Ich habe den Beitrag aktualisiert.) - Mei


Du schreibst:

Außerdem schreibt die Anwendung nicht stdout...

Haben Sie versucht, sich in die "Datei" einzuloggen? /dev/stdout? Dadurch können Sie möglicherweise Folgendes tun:

app --logfile /dev/stdout | logger -t app

1
2018-02-20 16:43



Ist das anders als bei einem FIFO? Was sind die Fehler? Ich suche keine Alternative, an sich; Ich suche nach einem Einblick, ob der von mir aufgeführte Ansatz robust ist. Das ist alles, was mich interessiert. - chrisaycock
Ja, es ist anders als ein FIFO; Es ist im Wesentlichen eine Datei, die mit STDOUT verbunden ist. Sie können das also verwenden, um sich bei STDOUT anzumelden und von dort nach syslog oder ähnlichem. Es ist als Lösung für Ihr ursprüngliches Problem gedacht, aber hoffentlich robuster als ein FIFO, da weniger bewegliche Teile vorhanden sind. - nickgrim


Es hat keinen Sinn, in einen FIFO zu schreiben und dann einen anderen Prozess in eine Datei schreiben zu lassen. Schreibe einfach direkt in die Datei und einmal die write() kehrt zurück, es liegt in den Händen des Kernels; Es wird immer noch auf die Festplatte schreiben, wenn die Anwendung abstürzt.


1
2018-02-21 23:06



Jede Protokollnachricht wird gelöscht: Diese blockieren Schreibvorgänge. Wir haben keine Kontrolle darüber, da wir den Quellcode der Anwendung nicht haben. - chrisaycock
@chrisaycock, richtig ... also wo ist das Problem? - psusi
Meine Kollegen und ich waren neugierig, wie wir die Leistungseffekte der Pufferung erzielen und gleichzeitig sicherstellen konnten, dass die Protokollnachricht den Prozess verlassen hat. - chrisaycock
@chrisaycock, ohh, so verwendet die Anwendung derzeit O_SYNC oder fsync() zu warten, bis jeder Schreibvorgang die Festplatte erreicht hat, und Sie wollen das NICHT (Risikoverlust im Falle eines Systemabsturzes)? - psusi
@chrisaycock, es hat nichts mit der Schnittstelle des Laufwerks zu tun, es bedeutet normalerweise nur, dass der Kernel es in den Dateisystem-Cache (und aus der Anwendung) kopiert hat. Wie ich in meiner Antwort ursprünglich sagte, einmal write() zurückgekehrt ist, kann die App abstürzen, wie es will - die Daten werden es auf die Festplatte machen, solange der Kernel nicht abstürzt. - psusi