Wie kann ich die Ausgabe eines laufenden Prozesses in einer anderen Bash-Sitzung anzeigen?


199

Ich habe ein Skript auf einem Remotecomputer ausgeführt, als ich lokal daran gearbeitet habe. Ich kann mich über SSH mit dem Computer verbinden und sehe, wie das Skript ausgeführt wird ps.

$ ps aux | grep ipcheck
myuser  18386  0.0  0.0  18460  3476 pts/0    S+   Dec14   1:11 /bin/bash ./ipchecker.sh

Es wird einfach in einer lokalen Sitzung auf stdout ausgegeben (ich habe es über ./ipchecker.shein lokales Terminalfenster ausgeführt, keine Umleitung, keine Verwendung von screenusw.).

Gibt es überhaupt eine SSH-Sitzung, in der ich die Ausgabe dieses ausgeführten Befehls anzeigen kann (ohne ihn zu stoppen)?

Bisher ist das Beste, was ich gefunden habe, die Verwendung, strace -p 18386aber ich bekomme eine Menge Text über den Bildschirm, der viel zu detailliert ist. Ich kann anhalten straceund dann die Ausgabe sichten und feststellen, dass der Text auf stdout gedruckt ist, aber er ist sehr lang und verwirrend, und natürlich kann ich etwas übersehen, wenn er angehalten ist. Ich möchte einen Weg finden, um die Skriptausgabe live zu sehen, als ob ich lokal arbeiten würde.

Kann jemand dies verbessern? Die offensichtliche Antwort ist, das Skript mit Umleitung oder in einer screenSitzung usw. neu zu starten. Dies ist kein geschäftskritisches Skript, also könnte ich das tun. Eher aber sehe ich das als lustige Lernübung.


Läuft Ihr Prozess in einer virtuellen Konsole oder in einer GUI / xterm-ähnlichen Umgebung?
jippie

4
Sie können die Ausgabe von strace auf einen Systemaufruf beschränken:strace -p 4232 -e write
otokan

@jippie Auf der Maschine läuft eine vollständige GUI (Linux Mynt 13, XFCE-Desktop). Ich habe ein Gnome-Terminal gestartet.
Jwbensley

3
Es gibt mindestens ein Dutzend ähnlicher Fragen auf dieser Website. Suchen Sie hier nach Reptyr , um einige von ihnen (und eine Antwort) zu finden.
Stéphane Chazelas

Antworten:


180

Wenn Sie nur den vorhandenen Prozess ausspionieren möchten, können Sie verwenden, strace -p1234 -s9999 -e writewobei 1234 die Prozess-ID ist. ( -s9999Vermeiden Sie, dass Zeichenfolgen auf 32 Zeichen gekürzt werden und writeder Systemaufruf eine Ausgabe erzeugt.) Wenn Sie nur Daten anzeigen möchten, die in einen bestimmten Dateideskriptor geschrieben wurden, können Sie so etwas wie strace -p1234 -e trace= -e write=3nur Daten anzeigen, die in den Dateideskriptor 3 geschrieben wurden (dies -e trace=verhindert das System) Anrufe werden protokolliert). Dadurch erhalten Sie keine bereits produzierte Ausgabe.

Wenn die Ausgabe zu schnell gescrollt wird, können Sie sie an einen Pager wie leiten lessoder an eine Datei mit senden strace -o trace.log ….

Bei vielen Programmen können Sie die nachfolgende Ausgabe mit einem Ptrace-Hack entweder zu Ihrem aktuellen Terminal oder zu einer neuen Bildschirmsitzung umleiten. Siehe Wie kann ich einen laufenden Prozess deaktivieren und einer neuen Bildschirmshell zuordnen? und andere verknüpfte Threads.

Beachten Sie, dass Sie abhängig von der Einrichtung Ihres Systems möglicherweise alle diese straceBefehle als Root ausführen müssen, auch wenn der Prozess unter Ihrem Benutzer ohne zusätzliche Berechtigungen ausgeführt wird. (Wenn der Prozess als ein anderer Benutzer ausgeführt wird oder setuid oder setgid ist, müssen Sie straceals root ausgeführt werden.) Die meisten Distributionen ermöglichen nur die Nachverfolgung der untergeordneten Prozesse (dies bietet einen moderaten Sicherheitsvorteil - es wird eine direkte Malware-Injektion verhindert.) verhindert aber nicht das indirekte Einfügen durch Ändern von Dateien. Dies wird vom kernel.yama.ptrace_scomesysctl gesteuert .


18
Ich vermute nicht, dass es eine Möglichkeit gibt, die Ausgabe auf die Standardausgabe einzugrenzen .
Jonah

3
Können Sie alle Argumente erklären?
Benutzer

6
Es gab viele Backslashes und Zahlen in vielen Ausgaben, die ich von nodejs erhielt; Gibt es Hinweise darauf, in welcher Codierung sie sich befinden könnten? Es gab auch jede Menge Klartext, was alles war, was ich brauchte.
ThorSummoner

3
"Können Sie alle Argumente erklären?" @ Benutzer:man strace
Pistos

3
@RafaelMoni Ein Programm, das das tut, was Sie verlangen, wird Debugger genannt.
Gilles

139

Sie können über das procDateisystem auf die Ausgabe zugreifen .

tail -f /proc/<pid>/fd/1

1= stdout, 2= stderr


7
Es gibt mir: "Kann / proc / <meine pid> / fd / 1 nicht zum Lesen öffnen: Kein solches Gerät oder keine solche Adresse".
Jaroslaw Nikitenko

18
Ja, <meine PID> sollte Ihre Prozess-ID sein
tvlooy

29
Dies funktioniert nicht, wenn die Ausgabe auf ein tty (oder umgeleitet zu /dev/null) geht - es funktioniert nur, wenn die Ausgabe in eine Datei umgeleitet wird.
Mattdm

1
Getestet auf Ubuntu 16.04 und es funktioniert nicht. In einer Sitzung tue ich: ping google.esund in einer anderen als root: tail -f /proc/`pgrep ping`/fd/2und es wird nichts angezeigt.
david.perez

1
Du hast recht. Denn fd 1 und 2 sind symbolische Links zum Gerät / dev / pts. Sie können -fa pts Gerät nicht beenden. Planen Sie Ihren Ping-Befehl als Cronjob und machen Sie dasselbe. Schwanz -f wird dann funktionieren
tvlooy

9

In BSD können Sie verwenden, watchwelche Snoops ein bestimmtes tty, z

watch /dev/pts/0

Unter Linux ist es nicht möglich, wenn der Prozess zuvor nicht unter Multiplexer wie screenoder ausgeführt wurde tmux. Siehe auch: Reptyr : Hängen Sie einen laufenden Prozess an ein neues Terminal an

Es scheint der einzige Weg ist , den Prozess zu debuggen (zB strace, dtrace/ dtruss, gdb, lldb, etc.).

Da Sie verwendet haben strace, um eine aussagekräftige Ausgabe abzurufen, müssen Sie nach einem qualifizierenden Ausdruck (z. B. file) filtern und dann die Ausgabe analysieren. Hier ist ein Beispiel:

strace -e trace=write -s1000 -fp 18386 2>&1 | grep -o '".\+[^"]"'

Was es tut, druckt eine Schreiboperation des Prozesses (1000 Länge), der durch die PID spezifiziert ist (verwendet pgrep, um ihn durch den Namen zu finden), leitet einen Standardfehler in die Ausgabe um (um gefiltert zu werden) und druckt eine Zeichenkette in doppelten Anführungszeichen.

Wenn Sie mit Binärausgabe arbeiten, können Sie Escape-Zeichen mit read(mit -r) und printf (mit %b) analysieren , z

while read -r -t1 line; do printf "%b" $line; done

Prüfen Sie , ob help readweitere Parameter vorhanden sind (z. B. -num nach einer bestimmten Anzahl von Zeichen anstatt nach einer neuen Zeile zu drucken).

Hier ist ein vollständigeres Beispiel:

strace -e trace=write -s1000 -fp 18386 2>&1 \
| grep --line-buffered -o '".\+[^"]"' \
| grep --line-buffered -o '[^"]\+[^"]' \
| while read -r line; do
  printf "%b" $line;
done

Überprüfen Sie für Beispiele, die einen beliebigen Prozess verwenden, Folgendes : Wie kann eine Shell-Verknüpfung in einfachen Text umgewandelt werden? bei Stapelüberlauf


4
  1. Sie könnten in der Lage sein auf dem Remote - Bildschirm spähen mit ssh localhost 'DISPLAY=:0.0 xwd -root' | xwud -scaledenen localhostvon Remote - Server Anmeldeinformationen ersetzt werden soll , und :0.0mit der Display - Nummer Ihrer GUI.

  2. Verwenden Sie x11vnceinen VNC-Server für Ihre Bildschirm-X-Sitzung.

  3. Wenn Sie auf einer der 6 virtuellen Konsolen laufen, versuchen sudo setterm -dump 2 -file /dev/stdoutSie, diese 2durch die entsprechende virtuelle Konsole zu ersetzen .


4

Ich würde empfehlen, eine Named Pipe ( mkfifo) zu erstellen und dann in diese Datei zu schreiben. Lesen Sie dann daraus. Sie können dies immer mit Dingen wie tailMinimieren der Ausgabe usw. tun . Wenn Sie die Pipe löschen (daraus lesen), wird sie gelöscht, sodass die Ausgabe nicht beibehalten wird.

Die andere Möglichkeit wäre, alles in eine Datei zu schreiben (ähnlich einer Protokolldatei) und sie dann jederzeit zu analysieren. Dies ist die bevorzugte Aktion, wenn Sie die gesamte Ausgabe beibehalten möchten.


3

Sie können immer einen Prozess mit nohup und & starten.

nohup rsync source_file dest_file &

Dann können Sie den Fortschritt von jedem Zeitpunkt an überprüfen mit:

tail -f nohup.out

Das funktioniert gut für mich.


6
Diese Frage würde ich über das Anzeigen der Ausgabe eines laufenden Prozesses Warnung, nicht wie Sie einen Prozess im Hintergrund
ausführen,

In der Tat, Ihre: Nohup Erwähnung erleuchten mich! Vielen Dank!
Nam G VU

1

Eine sehr einfache Möglichkeit, die Ausgabe zu erhalten, besteht darin, Ihre Ausgabe in einer Datei zu erfassen und diese Datei zu verfolgen.

WENN TUN: ./ipcheck

STATT DO: ./ipcheck> [durch Ihren Dateinamen ersetzen]

Dies würde eine Ausgabedatei erstellen, in der sich Ihr Skript befindet. Von jeder anderen Bash-Shell aus können Sie die Datei dann einfach mit einem Tail versehen:

tail [Ersetze deinen Dateinamen] -f


Bei der Dateiumleitung wird standardmäßig blockbasiertes Puffern verwendet (siehe setbuf(3)), was zu tailProblemen führen kann.
Thrig

5
Dies hilft auch nicht bei der Frage, wie die Ausgabe eines bereits laufenden Prozesses angezeigt werden soll und nicht, wie stdout für einen neuen Prozess umgeleitet werden soll.
Jwbensley

1

Analyse der Ausgabe von strace:

Ich habe die Top-Antwort verwendet (mit meiner Prozess-ID von 28223) ...

> sudo strace -p28223 -s9999 -e write
...
write(9, "Info\nI\nCare\nabout", 55) = 55
...

Um festzustellen, dass es mir wichtig ist write(9. (Die 9 wird unten verwendet, ist wahrscheinlich ein Datei-Handle und kann für Ihren Prozess unterschiedlich sein.) Dann habe ich ein schnelles Ruby-Skript geschrieben, um sie zu analysieren und anzuzeigen.

Fügen Sie Folgendes ein in /usr/bin/parse_strace.rb

#!/usr/bin/ruby

num = ARGV[0]
STDIN.each { |line|
  if (line.match(/write\(#{ num },\s*"(.*?)"/)) then
    puts $1.split('\x').map { |s| s.to_i(16).chr }.join()
  end
}

Nicht vergessen chmod a+x /usr/bin/parse_strace.rb

Ich rufe auf strace -xx(gibt hex aus, damit der reguläre Ausdruck richtig übereinstimmt) und leite (einschließlich STDERR) 9als erstes Argument an mein Skript .

sudo sh -c 'strace -xx -p28223 -s9999 -e write 2>&1 | parse_strace.rb 9'

Und voila, es gibt das ursprüngliche STDOUT, die Zeilenumbrüche, die Farbe und alles des Prozesses aus!

Anhängen, um STDOUT zu verarbeiten


0

Können Sie die Prozess-ID nicht abrufen und mit USR1 kommunizieren?

$pgrep -l '^ipchecker.sh$'

Das druckt die PID Ihres Skripts und verwendet sie dann für

$ kill -USR1 PID

Ich verstehe, dass USR1 ein "benutzerdefiniertes" Signal ist, was bedeutet, dass jeder, der das Programm erstellt hat, damit "Herunterfahren" oder "Ihre Protokolle sichern" oder "tausendmal drucken" oder was auch immer bedeuten kann.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.