Schauen Sie sich den Inhalt von stdin an

7

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 catund 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.

John Saxton
quelle
tolle Frage! Ich habe versucht, dasselbe zu tun wie gestern und Viola - es gibt eine Frage.
Sergiy Kolodyazhnyy

Antworten:

3

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.

# cat >/tmp/foofile


# ps -ef|grep cat
steve     2134  1801  0 22:25 pts/2    00:00:00 cat
# strace -fp 2134
Process 2134 attached
read(0, "test\n", 65536)                = 5
write(1, "test\n", 5)                   = 5
read(0,

So löschen Sie einfach die Lesevorgänge aus dem Dateideskriptor 0:

strace -fp 2134 -e trace=read -o "|grep read.0,"
Steve
quelle
Danke für den Vorschlag. Kennen Sie eine Möglichkeit, längere Zeichenfolgen auszudrucken? $ Strace -fp pidof catProzess 25975 angebracht - Interrupt lesen zu beenden (0, "afdkjdjakskljjjjjjjjjjjjjjjjjjjj" ..., 32768) = 4096 write (1, "afdkjdjakskljjjjjjjjjjjjjjjjjjjj" ..., 4096) = 4096 Lese (0, Danke, John
John Saxton
1
Ah, es sieht so aus, als gäbe es einen "-s" -Parameter, der den Trick macht.
John Saxton
1
Mein aktueller Befehl ist strace -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.
John Saxton
@JohnSaxton -e read=0gibt Ihnen nur einen schönen Speicherauszug der Standardeingabe.
Gilles 'SO - hör auf böse zu sein'
Vielen Dank an Steve für die Aktualisierung der Antwort -o "|grep read.0,". Der letzte Befehl, den ich benutze, ist strace -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.
John Saxton
0

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, ist teedie Eingabe in diese Datei und in stdout. Und so , was ich in der Regel tun , wenn ich mich in Ihrer Situation (wie ich oft) ist teeEingang off sowohl auf meiner Leseanwendung und /dev/fd/2- stderr.

So was:

seq 10 | tee /dev/fd/2 | wc -c
1
2
3
4
5
6
7
8
9
10
21

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 E tty/ A- luitVorgänge protokollieren, indem ich meinen Befehl einpacke - weil ich es für die bequemere der beiden halte -, obwohl scriptdies auch auf die gleiche Weise funktionieren könnte.

luitist wahrscheinlich bereits auf Ihrem System installiert - es ist normalerweise mit verpackt xterm- 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:

luit -olog /dev/fd/2 sh -c 'read var; echo "$var"'
eecchhoo  tthhiiss  vvaarr??????

echo this var???
echo this var???

Wie Sie sehen können, werden luitin der benannten -ologDatei alle empfangenen Terminaleingaben protokolliert, sobald dies der Fall ist.

Die Verwendung /dev/fd/2ist 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 dem ttyBefehl, und verwenden , die /dev/pts/[0-9]Namen wie luit/ 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. teekann 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. straceDies 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 -TRAPIhren Prozess jedes Mal anhält, wenn er einen Systemaufruf ausführt.

mikeserv
quelle
-1

Eine Möglichkeit (wenn das andere Dinge nicht kaputt macht) besteht darin, einen Anruf bei einzufügen tee. Der Befehl teedupliziert die Daten, sodass eine Kopie in Ihre Anwendung und eine in die Debug-Ausgabe gelangen kann. Anstatt aufzurufen your_application, vereinbaren Sie einen Aufruf tee 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 :

strace -e read=0 -e trace=read -e signal=none your_application 2>&1 |
grep '^ |'
Gilles 'SO - hör auf böse zu sein'
quelle