Ich versuche, eine Linux-Anwendung zu debuggen, die Befehle über stdin empfangen kann, und es wäre wirklich nützlich, alles zu sehen, was in stdin geschrieben wird.
Mein erster Ansatz war die Ausführung sudo cat /proc/$pid/fd/0
, aber es stellt sich heraus, dass dies ein ungültiger Ansatz ist, da beide cat
und mein Prozess versuchen, den Inhalt dieses Dateideskriptors zu verbrauchen, und nur ein Prozess das Rennen gewinnen kann.
Ein anderer Ansatz wäre die Verwendung von Schwanz, aber das funktioniert aus den hier genannten Gründen nicht .
Ich könnte meiner Anwendung leicht eine Debug-Protokollierung hinzufügen, und das würde das Problem lösen, aber ich bin interessiert zu wissen, ob es einen allgemeineren Ansatz gibt, den ich vermisse.
Antworten:
strace
?Beispiel unten. Starten Sie einen Cat-Prozess, der stdin liest und in / tmp / foofile schreibt. Finden Sie die PID, straffen Sie sie. Und geben Sie im ursprünglichen Katzenfenster einen Text ein, hey presto.
So löschen Sie einfach die Lesevorgänge aus dem Dateideskriptor 0:
quelle
pidof cat
Prozess 25975 angebracht - Interrupt lesen zu beenden (0, "afdkjdjakskljjjjjjjjjjjjjjjjjjjj" ..., 32768) = 4096 write (1, "afdkjdjakskljjjjjjjjjjjjjjjjjjjj" ..., 4096) = 4096 Lese (0, Danke, Johnstrace -s 4096 -e trace=read -fp 26471
. Der Prozess, den ich debugge, führt viele zusätzliche E / A durch, daher versuche ich, eine Möglichkeit zum Filtern zu finden, damit nur Lesebefehle von stdin gedruckt werden, keine anderen Dateideskriptoren. Ich werde sicher ein Update veröffentlichen, sobald ich es herausgefunden habe.-e read=0
gibt Ihnen nur einen schönen Speicherauszug der Standardeingabe.-o "|grep read.0,"
. Der letzte Befehl, den ich benutze, iststrace -s 4096 -e trace=read -fp $pid -o "|grep read.0,"
. Ich bin ein wenig besorgt wegen des mit strace verbundenen Leistungseinbruchs, aber dies ist die beste Lösung, die ich finden kann. Deshalb werde ich dies als akzeptierte Antwort markieren.Unter Linux können Sie die Dateideskriptoren einer Anwendung als benannte Dateien in adressieren
/dev/fd/[0-9]
. Und was Sie definitiv mit einer benannten Datei und einem Eingabestream tun können, isttee
die Eingabe in diese Datei und in stdout. Und so , was ich in der Regel tun , wenn ich mich in Ihrer Situation (wie ich oft) isttee
Eingang off sowohl auf meiner Leseanwendung und/dev/fd/2
- stderr.So was:
Selbst wenn Sie nicht auf einem Linux-System wären, könnte das Gleiche natürlich portabel gemacht werden - wenn auch in einigen Fällen weniger spezifisch - indem Sie es einfach tun
...| tee /dev/tty | ...
Wenn Sie über das Terminal sprechen, wenn Sie sagen
stdin
(wie Ihr Link anzeigt) , können Sie immer noch dasselbe tun, obwohl es auf diese Weise aufgrund der Zeilenpufferung des Kernels etwas schwieriger werden kann. In diesem Fall würde ich also alle Etty
/ A-luit
Vorgänge protokollieren, indem ich meinen Befehl einpacke - weil ich es für die bequemere der beiden halte -, obwohlscript
dies auch auf die gleiche Weise funktionieren könnte.luit
ist wahrscheinlich bereits auf Ihrem System installiert - es ist normalerweise mit verpacktxterm
- und es ist ein sehr einfaches CLI-Tool, das für UTF-8-Übersetzungen vorgesehen ist (diese Funktion kann möglicherweise vollständig über den CLI-Schalter deaktiviert werden, aber ich habe nie einen Grund dafür gefunden dies tun) für Terminalanwendungen, die es nicht verstehen.Es funktioniert, indem es seine eigene Pty - für die es den Master-FD besitzt - unter die aktuelle Tty-Ebene legt und alle E / A aus der aktuellen Sitzung in die untergeordnete Ebene kopiert, wo es Ihre angeforderte Anwendung ausführt. Da es das Master-Ende besitzt, kann es leicht alle E / A-Vorgänge duplizieren, die es an anderer Stelle liest / schreibt, wie es möchte, und es bietet eine bequeme Möglichkeit, es dazu aufzufordern:
Wie Sie sehen können, werden
luit
in der benannten-olog
Datei alle empfangenen Terminaleingaben protokolliert, sobald dies der Fall ist.Die Verwendung
/dev/fd/2
ist in diesem Fall bei weitem nicht so nützlich, da alle E / A-Vorgänge zweimal am selben Ort ausgeführt werden. Ich ziehe es in der Regel ein zweites Terminal zu öffnen, Abfrage seinen Namen mit demtty
Befehl, und verwenden , die/dev/pts/[0-9]
Namen wieluit
/script
‚s genannt outfile - die alle von der kopiert i / o an beide Anschlüsse gleichzeitig - so kann ich es auf der einen Lese- / Bewertung und interagieren mit ihm auf der anderen Seite.tee
kann in den meisten Fällen verwendet werden, um dasselbe zu tun, hat jedoch normalerweise nicht den Vorteil, dass das Master-Ende eines Pty es empfiehlt.Wenn Ihr Ziel genau so ist, wie Sie es sagen - alle Eingaben eines Prozesses für Ihre Überprüfung zu kopieren -, sollten Sie sich wahrscheinlich am besten auf die Eingaben konzentrieren.
strace
Dies ist für viele Dinge nützlich. Wenn Sie jedoch versuchen, einen genauen Bericht über das typische Verhalten zu erhalten, sollten Sie dieses Verhalten beim Sammeln Ihres Berichts wahrscheinlich so wenig wie möglich ändern. Mit anderen Worten, wenn Sie eine Eingabe wünschen, kopieren Sie die Eingabe, fügen Sie keinen übergeordneten Debugging-Prozess ein, der-TRAP
Ihren Prozess jedes Mal anhält, wenn er einen Systemaufruf ausführt.quelle
Eine Möglichkeit (wenn das andere Dinge nicht kaputt macht) besteht darin, einen Anruf bei einzufügen
tee
. Der Befehltee
dupliziert die Daten, sodass eine Kopie in Ihre Anwendung und eine in die Debug-Ausgabe gelangen kann. Anstatt aufzurufenyour_application
, vereinbaren Sie einen Aufruftee input.log | your_application
. Wenn die Eingabe in Ihre Anwendung eine Datei war, handelt es sich nicht um eine invasive Änderung. Wenn es sich jedoch nicht um eine Pipe handelt, wird sie zu einer Pipe, was Konsequenzen hat (z. B. ist eine Pipe nicht durchsuchbar).Eine andere Möglichkeit besteht darin, die von Ihrer Anwendung ausgeführten Dateilesevorgänge zu verfolgen. Sie können dies mit strace tun :
quelle