Ich habe einen Befehl ausgeführt und seine Ausgabe umgeleitet über > /dev/null
Jetzt, da er deutlich länger ausgeführt wird als erwartet, möchte ich sehen, was er tut.
Gibt es eine Möglichkeit, die Ausgabe so umzuleiten, dass alle neuen Inhalte gedruckt werden stdout
? Mir ist klar, dass alle vorherigen Inhalte weg sind.
linux
bash
operating-systems
Mikhail
quelle
quelle
Antworten:
Sie können es mit strace tun.
Mit können
strace
Sie ausspionieren, was in den Dateideskriptor 1 geschrieben wird, der der Standard-Dateideskriptor ist. Hier ist ein Beispiel:Möglicherweise möchten Sie den Filter verbessern, aber das wäre eine andere Frage. Wir haben die Ausgabe, müssen sie aber jetzt aufräumen.
: WARNUNG: Diese Lösung weist einige Einschränkungen auf, siehe Kommentare unten. Es wird nicht immer funktionieren, Ihr Kilometerstand kann variieren.
Prüfung:
Legen Sie dieses Programm (unten) in die Datei
hello
undchmod +x hello
Dieser in
hello1
undchmod +x hello1
Dieser in
hello2
undchmod +x hello2
Führen Sie dann mit aus
./hello2 >/dev/null
, suchen Sie die PID des Prozesses Hallo und geben Sie ein,pid_of_process_you_want_to_see_stdout_of=xyz
wobei xyz die PID des Hallo ist. Führen Sie dann die Zeile oben aus.Wie es funktioniert. Wenn Hallo ausgeführt wird, Bash-Gabeln, leitet fd 1 an weiter
/dev/null
und führt dann Hallo aus. Hello sendet die Ausgabe per Systemaufruf an fd1write(1, …
. Kernel empfängt Systemaufrufwrite(1, …
, sieht, dass fd 1 verbunden ist/dev/null
und…Wir führen dann strace (Systemaufruf-Trace) auf Hallo aus und sehen, dass es
write(1, "hello\nworld\n")
den Rest aufruft, wenn die obige Zeile nur die entsprechende Zeile des Trace auswählt.quelle
hello2
, welche Anrufehello1
, welche Anrufehello
, und dann die PID des Prozesses (dh das Kind des Kindes) finden und den Befehl für diese PID ausführen ." Ich stimme @NicoleHamilton zu - Sie haben ihren Kommentar nicht angesprochen. Wenn Sie Ihren Befehl auf einen Prozess anwenden , der bereits Kinder hervorgebracht hat, wird die Ausgabe der Kinder nicht erfasst. Wenn Sie Ihre Antwort ändern, um den Befehl auf den Enkelprozess anzuwenden, wird das Problem behoben. … (Fortsetzung)hello
strace
strace
hello
Skript besagtecho … > /dev/null
, würde Ihre Lösung fehlschlagen. Ich gebe zu, dass es nahezu unmöglich wäre, mit dieser Situation umzugehen, und mir ist klar, dass Sie (in einem Kommentar) zugeben, dass Sie nur eine 90% ige Lösung vorgelegt haben. Es ist jedoch besser, die Einschränkungen und Einschränkungen Ihrer Antwort in der Antwort anzugeben .Nein, Sie müssen den Befehl neu starten.
Stdio-Handles werden vom übergeordneten zum untergeordneten Prozess vererbt. Sie haben dem Kind / dev / nul einen Griff gegeben. Es ist kostenlos, damit zu tun, was immer es will, einschließlich Dinge wie dup () 'es oder die Weitergabe an seine eigenen Kinder. Es gibt keine einfache Möglichkeit, in das Betriebssystem zu gelangen und zu ändern, worauf die Handles eines anderen laufenden Prozesses verweisen.
Möglicherweise können Sie einen Debugger für das untergeordnete Element verwenden und dessen Status zappen, alle Speicherorte, an denen eine Kopie des aktuellen Handle-Werts gespeichert ist, mit etwas Neuem überschreiben oder seine Aufrufe an den Kernel verfolgen und alle E / A überwachen. Ich denke, das fordert viele Benutzer auf, aber es kann funktionieren, wenn es sich um einen einzelnen untergeordneten Prozess handelt, der mit dem I / O nichts Lustiges macht.
Aber selbst das schlägt im allgemeinen Fall fehl, z. B. ein Skript, das Pipelines usw. erstellt, Handles täuscht und viele eigene Kinder erstellt, die kommen und gehen. Aus diesem Grund müssen Sie nicht mehr von vorne anfangen (und möglicherweise zu einer Datei umleiten, die Sie später löschen können, auch wenn Sie sie jetzt nicht sehen möchten.)
quelle
Ich habe lange nach der Antwort auf diese Frage gesucht. Es stehen hauptsächlich zwei Lösungen zur Verfügung:
In meinem Fall war keiner von ihnen zufriedenstellend, da zuerst die Ausgabe abgeschnitten wurde (und ich sie nicht länger einstellen konnte). Das zweite kommt nicht in Frage, da auf meiner Plattform keine GDB installiert ist - es ist ein eingebettetes Gerät.
Ich sammelte einige Teilinformationen im Internet (habe sie nicht erstellt, sondern nur zusammengestellt) und bin mithilfe von Named Pipes (FIFOs) zur Lösung gelangt. Wenn der Prozess ausgeführt wird, wird seine Ausgabe an die Named Pipe geleitet, und wenn niemand sie sehen möchte, wird ein dummer Listener (tail -f >> / dev / null) darauf angewendet, um den Puffer zu leeren. Wenn jemand diese Ausgabe erhalten möchte, wird der Endprozess abgebrochen (andernfalls wird die Ausgabe zwischen den Lesern gewechselt) und ich katze die Pipe. Am Ende des Hörens startet ein weiterer Schwanz.
Mein Problem war es also, einen Prozess zu starten, die SSH-Shell zu beenden, mich dann erneut anzumelden und die Ausgabe abzurufen. Dies ist jetzt mit folgenden Befehlen möglich:
Das Skript, das dies erreicht, ist unten angefügt. Mir ist bewusst, dass es keine perfekte Lösung ist. Bitte teilen Sie Ihre Gedanken, vielleicht wird es hilfreich sein.
quelle
Sie können dies mit dem Reredirect- Programm tun :
Sie können die anfängliche Ausgabe Ihres Prozesses später wiederherstellen, indem Sie Folgendes verwenden:
(
<M>
und<N>
werden durch vorherigen Start von Reredirect bereitgestellt).reredirect
README
erklärt auch, wie man zu einem anderen Befehl umleitet oder nur stdout oder stderr umleitet.quelle