Wie kann ich stdout / stderr eines bereits laufenden Prozesses umleiten?

7

(Läuft auf einem Ubuntu 10.04 64-Bit-Server)

Gestern habe ich den Fehler gemacht, einen Prozess über SSH zu starten (von dem ich nicht wusste, dass er mehrere Tage dauern würde), ohne den Bildschirm zu verwenden. Ich habe heute den ganzen Tag damit verbracht, herauszufinden, wie ich die Ausgabe des Prozesses aus dem Eisengriff von SSH herausholen kann, damit ich meinen Client-Computer neu starten kann, aber nicht weiterkomme.

Ich habe versucht, gdb zu verwenden und den Anweisungen am Ende dieser Seite zu folgen. Wenn ich jedoch den ersten gdb-Befehl zum Erstellen einer Datei ausführe, wird eine Fehlermeldung angezeigt, die besagt No symbol table is loaded. Use the "file" command. , dass ich das Programm, dessen Ausgabe ich habe, neu kompilieren muss Ich versuche umzuleiten, was mir jetzt natürlich keine Hilfe ist, da es bereits läuft.

Ich dachte auch, ich könnte Retty verwenden, um die Ausgabe auf ein anderes Terminal umzuleiten, aber offensichtlich wird es auf 64-Bit-Plattformen nicht kompiliert.

Wie kann ich die Ausgabe dieses Prozesses auf ein anderes Terminal oder eine Datei umleiten?

nonoitall
quelle

Antworten:

5

Es sieht so aus, als ob diese Anweisungen gdbin mehrfacher Hinsicht falsch und unvollständig sind.

Zuerst müssen Sie verwenden

gdb [executablefile] [pid]

so dass GDB weiß , was das Programm es tatsächlich zu verbinden ist ist . Ich habe dies gerade getestet und es kann eine gestrippte ausführbare Datei verwenden. Beachten Sie, dass der Prozess angehalten wird, während gdb an den Prozess angehängt ist. Wenn dieser Prozess über ein Netzwerk kommuniziert, geben Sie schnell ein, da sonst die Zeit für die Netzwerkverbindung abläuft.

Zweitens erklären die angegebenen Befehle nicht, was sie tun, und die Anweisung, "in ein Verzeichnis zu schreiben, in das Ihr Programm Dateien schreiben soll", ist falsch, da gdb das ursprüngliche Programm auffordert, die creat()Funktion auszuführen . In dem angegebenen Beispiel werden die Dateien myprog.stderr und myprog.stdout im aktuellen Arbeitsverzeichnis des laufenden Programms erstellt, nicht in dem Verzeichnis, in dem Sie gdb ausgeführt haben. Verwenden Sie hier absolute Pfadnamen, wenn Sie nicht wissen, was die CWD dieses Programms ist (oder sehen ls -l /proc/[pid]/cwd).

Drittens ist es wichtig zu wissen, dass der erste Parameter dup2()die Dateideskriptornummer ist, die von der vorherigen zurückgegeben wurde. creat()Wenn in diesem laufenden Programm mehrere Dateien geöffnet waren, kann dies zu einem Austausch führen

(gdb) call creat("/home/me/myprog.stdout",0600)
$1 = 7
(gdb) call dup2(7,1)
$2 = 1
(gdb) call creat("/home/me/myprog.stderr",0600)
$3 = 8
(gdb) call dup2(8,2)
$4 = 2

Wenn Sie gdb beenden, werden Sie gefragt, ob Sie "trotzdem beenden (und abnehmen)" möchten. Die Antwort lautet "Ja".

Schließlich bgund disownsind Bash Builtins. Wenn Sie Bash nicht verwendet haben, sind Sie von hier aus allein. bgVerschiebt einen angehaltenen Job in den Hintergrund, als ob er dort mit gestartet worden wäre somecommand &, und disownentfernt das Programm aus der Liste der aktiven Programme von bash nach SIGHUP, wenn bash beendet wird.

DerfK
quelle
Ich habe Ihre Anweisungen befolgt und die Befehle entsprechend geändert, und diesmal waren die Befehle erfolgreich! Es wird jedoch nichts in die erstellten Dateien geschrieben. Derzeit lautet ls -l / proc / [pid] / fd wie folgt (abzüglich der irrelevanten Bits): 0 -> / dev / pts / 0 (gelöscht); 1 -> / dev / pts / 0 (gelöscht); 2 -> / dev / pts / 0 (gelöscht); 3 -> / dev / sdb; 4 -> /root/myprog.stdout; 5 -> /root/myprog.stdout; 6 -> /root/myprog.stderr; 7 -> /root/myprog.stderr (Und falls Sie sich fragen, wird der Prozess in Frage wird als root ausgeführt wird , so sollte es auf diese Dateien schreiben können.)
nonoitall
call dup2()Dann ist etwas schiefgegangen , es hätte die fd für "myprog.stdout" über fd 1 duplizieren sollen, anstatt eine neue fd 5 zu erstellen. Sie sollten dies immer noch beheben können, wenn Sie gdb und call dup2(4,1)und wiederholen call dup2(6,2). Hoffentlich stört die zusätzliche Kopie der geöffneten Datei nicht, aber probieren Sie call close(5)die Ersatzkopie nicht an. Ich habe das gerade getestet und das Programm ist sofort fehlerfrei.
DerfK
Ah, ich sehe, was schief gelaufen ist. Ich hatte es eilig, die GDB-Befehle einzugeben, und ich ließ die '2' in 'dup2' weg. Im Moment scheint alles in Ordnung zu sein, da die Ausgabe in die von mir erstellte stderr-Datei geschrieben wird. Es sind noch ein paar zusätzliche Deskriptoren offen, aber es scheint nicht, dass sie Schaden anrichten. Vielen Dank!
nonoitall
0

Sie können nichts aus der Ferne tun. Melden Sie sich mit ssh und demselben Konto beim anderen Server an, mit dem der Prozess gestartet wurde. Sie können den Prozess von der neuen Sitzung aus steuern.

David Harris
quelle
Das habe ich getan. Ich muss noch wissen, was serverseitig funktionieren wird.
nonoitall
0

Sie können reredirect verwenden ( https://github.com/jerome-pouiller/reredirect/ ).

Art

reredirect -m FILE PID

und Ausgaben (Standard und Fehler) werden in FILE geschrieben.

reredirect README erklärt auch, wie der ursprüngliche Prozessstatus wiederhergestellt, wie zu einem anderen Befehl umgeleitet oder nur stdout oder stderr umgeleitet werden.

Jérôme Pouiller
quelle