So speichern Sie die Ausgabe einer seriellen Konsole lokal in einer Datei, ohne ein serielles Kabel

So speichern Sie die Ausgabe einer seriellen Konsole lokal in einer Datei, ohne ein serielles Kabel

Ich verwende eingebettetes Linux und meine Befehlszeile hat console=/dev/ttyO0,.... Ich habe ein Terminalprogramm an diesen UART angeschlossen und kann sehenallesvom System erzeugt.

Wenn ich jetzt im Feld arbeite, möchte ich die gesamte Ausgabe in der Datei speichern (ich habe das Medium angeschlossen). Aber alle meine Bemühungen mit syslogd, klogd, loggerund Co. führen nicht zum gewünschten Ergebnis - einige Nachrichten werden gespeichert, andere jedoch nicht - normalerweise die wichtigsten.

Wenn ich beispielsweise Folgendes ausführe:

myapplication.sh | logger        

echoBefehle sehe ich auch in syslog, prints aus der Anwendung, auch einige Treibermeldungen. Aber wenn die Anwendung mit einem Segmentierungsfehler abstürzt, wird diese Information nicht protokolliert. Aber das ist äußerst wertvoll!

Die beste und wünschenswerteste Möglichkeit besteht also in der Weiterleitung ttyO0zu einer Datei. Aber wie?

Ich habe folgende Empfehlung gefunden:

(stty raw; cat > received.txt) < /dev/ttyO0

aber das funktioniert nicht: Ich kann einen Befehl eingeben, z. B. ifconfig, aber die Antwort erscheint weder in der Datei noch auf der Konsole. Nicht einmal die Datei wird erstellt...:-(

Wenn es möglich ist, beides zu haben – Datei und serielle Konsole – wäre das großartig. Aber die Datei hat höhere Priorität.

Vielen Dank für die Hilfe!

AktualisierenIch habe eine Lösung gefunden und sie im Antwortbereich hinzugefügt.

Antwort1

Sie scheinen eine ziemlich grundlegende Tatsache übersehen zu haben. Jedes pipeable Programm basiert auf der Tatsache, dass esdreiStandard-Dateideskriptoren in einem vorgeöffneten Zustand von jedem Programm, das sie aufruft. In den meisten Fällen, in denen Pipes verwendet werden, ist das aufrufende Programm die Befehlsshell.

Diese drei Dateideskriptoren sind:

  • Dateideskriptor Nr. 0: Standardeingabestrom oder stdinkurz.
  • Dateideskriptor Nr. 1: Standardausgabestrom, oder stdoutkurz.
  • Dateideskriptor Nr. 2: StandardFehlerausgabeStream, oder stderrkurz.

Wenn ein Programm nicht weitergeleitet oder umgeleitet wird, um eine Datei zu lesen/schreiben, dann verweisen alle diese drei Dateideskriptoren normalerweise auf ein TTY-Gerät, auf dem die aktuelle Anmeldesitzung ausgeführt wird. Wenn ein Programm absichtlich als Daemon oder Hintergrund-/nicht interaktiver Prozess gestartet wird, können alle diese Deskriptoren auf Datei(en) oder /dev/nulloder möglicherweise in eine Art Protokollierungseinrichtung geleitet werden.

Fehlermeldungen werden normalerweise in den stderrStream ausgegeben, damit sie nicht mit den möglicherweise weitergeleiteten Datenausgaben vermischt werden. Aber in Fällen wie Ihrem, wenn Sie erfassen möchtenalleUm die Ausgabe zu erhalten, müssen Sie dem System ausdrücklich mitteilen, dass beide Streams erfasst werden sollen.

Wenn Sie die gesamte Ausgabe von Ihnen an eine Pipe weiterleiten möchten myapplication.sh, müssen Sie möglicherweise Folgendes tun:

myapplication.sh 2>&1 | logger

Dort 2>&1steht: „Leiten Sie Dateideskriptor Nr. 2 an denselben Ort um, an den auch Dateideskriptor Nr. 1 geht“, und dann können Sie beide gleichzeitig weiterleiten.

Sie können es selbst mit einem kleinen Skript wie diesem testen:

#!/bin/sh
echo "this is stdout"
echo "this is stderr" >&2

Das >&2bedeutet „nimm die Standardausgabe dieses Befehls und sende sie stattdessen in den Standardfehlerstrom“. Dies ist wahrscheinlich die einfachste Möglichkeit, stderreine Ausgabe in einem Skript zu generieren.

Wenn Sie dieses Skript nun ausführen, ./test.sh | od -t x1zum seine Ausgabe im Hex-Dump-Format zu erhalten, erhalten Sie Folgendes:

$ ./test.sh | od -t x1z
this is stderr
0000000 74 68 69 73 20 69 73 20 73 74 64 6f 75 74 0a     >this is stdout.<
0000017

stdoutDaher wurde vom Befehl nur die Ausgabe verarbeitet od.

Wenn Sie das hinzufügen, 2>&1um beide Streams zusammenzuführen, erhalten Sie stattdessen Folgendes:

$ ./test.sh 2>&1 | od -t x1z
0000000 74 68 69 73 20 69 73 20 73 74 64 6f 75 74 0a 74  >this is stdout.t<
0000020 68 69 73 20 69 73 20 73 74 64 65 72 72 0a        >his is stderr.<
0000036

Jetzt wurden beide Ausgaben in die Pipeline gesendet, was in Ihrem Fall gewünscht ist | logger.


Ihre zweite Befehlszeile erfasst alles, was Ihr eingebettetes Gerät vom Terminalprogramm empfängt, und nicht, was das eingebettete Gerät an das Terminal sendet:

(stty raw; cat > received.txt) < /dev/ttyO0

Sie sagten, Sie arbeiten an einem eingebetteten System, das den Kernel-Parameter verwendet. Es wird sich console=/dev/ttyO0also im Wesentlichen /dev/consoleum einen seriellen Anschluss handeln und nicht um eine grafische Anzeige (die in einem eingebetteten Gerät möglicherweise nicht einmal vorhanden ist).

Wenn Sie diesen Befehl auf dem eingebetteten Gerät ausführen, werden die Befehle in den Klammern mit ihrenStandardeingabestream(Dateideskriptor Nr. 0 oder stdinkurz ) zugewiesen /dev/ttyO0. Wenn Sie den Befehl jedoch über die serielle Leitung eingeben ttyO0, die mit verbunden ist, wird dies wahrscheinlich standardmäßig der Fall sein, sodass diese Eingabeumleitung die Situation möglicherweise nur verstärkt.

Das /dev/ttyO0Gerät ist die direkte Darstellung des UART, das mit Ihrem Terminalprogramm auf dem anderen Computer verbunden ist. Wenn Sie davon lesen, erhalten Sienur was Sie in das Terminalprogramm eingeben: Es gibt keine Möglichkeit, zuvor gesendete Ausgaben wieder zu lesen. Und alles, was dort geschrieben wird, geht direkt an das Terminalprogramm am Ende des seriellen Kabels.

Die Unix-Kommandozeile auf einem seriellen Port funktioniert normalerweise auf einemFernbedienungsechoPrinzip: Um zu sehen, was Sie in das Terminalprogramm schreiben, muss der TTY-Treiber auf dem eingebetteten System eine Kopie jedes eingegebenen Zeichens direkt an das Terminalprogramm zurücksenden. Dieses Verhalten ist nicht symmetrisch: Das Terminalprogramm sendet keine Kopie von allem zurück, was es über die serielle Schnittstelle empfängt.

Der TTY-Treiber ist eine komplizierte Sache, da er aufgrund seiner Unix-Tradition viele Dinge können muss – die Remote-Echo-Funktion ist nur eines davon.

Wenn Sie verwenden stty raw, sind Sie effektivAusschalten aller normalerweise hilfreichen Funktionen des TTY-Treibers, einschließlich der Remote-Echo-Funktion. Ab diesem Punkt /dev/ttyS0sehen Sie also nicht, was Sie im Terminalprogramm schreiben, es sei denn, etwas liest explizit daraus und schreibt es sofort wieder hinein.

Sobald der stty rawBefehl beendet wurde, wird jede Eingabe aus dem Terminalprogramm in den catBefehl übernommen, der sie bei Aufruf ohne Parameter einfach so in seine Standardausgabe übergibt. Aber seine Standardausgabe wurde jetzt in eine Datei umgeleitet received.txt. Was also passiert, ist Folgendes:nur das, was Sie im Terminalprogramm eingeben, wird in die Datei geschriebenbis der catBefehl endet – und er endet erst, wenn er das Dateiende-Zeichen erhält (normalerweise Control+D).

(Aufgrund der Pufferung, die möglicherweise von der Shell durchgeführt wird, die die Umleitung durchführt, erfolgt möglicherweise keine Ausgabe in die received.txtDatei, es sei denn, Sie beenden Ihre Eingabe mit dem Dateiende-Zeichen und/oder geben mehr als eine Textzeile ein.)

Außer dem Ausschalten der TTY-Treiberfunktionen (stty raw; cat > received.txt) < /dev/ttyO0unternimmt das eingebettete System also überhaupt nichts, umAusgabein den geschrieben wird /dev/ttyO0. Dieser Befehl wird nur bei der Fehlerbehebung verwendet.Serielle Schnittstelle: Wenn Sie den Verdacht haben, dass Ihr Terminalprogramm die von Ihnen gesendeten Zeichen irgendwie verstümmelt, können Sie auf diese Weise alles, was das Terminalprogramm an das eingebettete Gerät sendet, in seiner rohesten Form erfassen.


Wenn Sie aufnehmen möchtenabsolut allesdas passiert über die UART-Verbindung, einschließlich z. B. Kernel-Panic-Meldungen, dann wäre es wahrscheinlich am besten, Ihr Terminalprogramm auf dem anderen Computer anzuweisen, den gesamten Datenverkehr zu protokollieren. Viele Terminalprogramme haben diese Funktion integriert.

Dies liegt daran, dass es bei einem Fehler im Kernel möglicherweise nicht mehr möglich ist, irgendetwas in eine Festplattendatei zu schreiben. Es ist viel einfacher, den Text der Fehlermeldung einfach über einen UART zu senden und darauf zu vertrauen, dass der Empfänger ihn auch erkennt.

Antwort2

OK, ich glaube, ich habe die Antwort gefunden. Ich bin sehr, sehr überrascht, dass eine so einfache und meiner Meinung nach erforderliche Sache auf so „unregelmäßige“ Weise gelöst wird, aber so ist das Leben … :-) Wie
auch immer, danke an telcoMdenjenigen, der mir die Referenzen gegeben hat, die zu Referenzen und noch mehr Referenzen führten und es mir schließlich ermöglichten, das Paket zu finden, das genau das tut, was ich wollte. Die Paketpflege wurde vor etwa 7-10 Jahren eingestellt und ich brauchte einige Zeit, um es an meine Linux-Version und die erforderlichen Bibliotheken anzupassen, aber es funktioniert! Es tut genau das, was ich wollte – sammelt die Ausgaben von ttyS0/ttyO0 und speichert sie in einer Datei. Und hat viele tolle Optionen, obwohl ich sie nicht brauche … :-)ttyrpl

Antwort3

Versuchen Sie, picocom anstelle von console=/dev/ttyS0 zu verwenden. Es gibt andere Tools, aber picocom scheint am einfachsten zu sein.

Wenn Sie eines dieser Werkzeuge verwenden, können Sie am Ausgang ein Rohr und ein T-Stück verwenden.

picocom /dev/ttyS0 -b 115200 -l | tee my.log

https://askubuntu.com/q/1010232

Antwort4

Versuchenhttps://tio.github.io- es unterstützt die Protokollierung in Dateien. Beispiel:

tio /dev/ttyS0 --log --log-file my-log.txt

Oder

tio /dev/ttyS0 --log

Dadurch wird die serielle Ausgabe in eine Datei mit automatisch generiertem Dateinamen protokolliert, beispielsweisetio_ttyS0_2022-09-14T08:56:09.log

verwandte Informationen