
Versehentlich gelöschte Protokolldatei des laufenden Prozesses python something.py 2>&1 | tee .log
. Das Skript läuft in einem Tmux-Bereich auf zsh. Der Prozess läuft noch, aber es wird nicht protokolliert. Die Ausgabe selbst führt zu einem Überlauf des Tmux-Scrollback-Puffer. Kann ich (Administrator-/Sudo-Rechte) den Protokollierungsprozess irgendwie erneut starten, ohne den Prozess neu zu starten?
Normalerweise funktioniert mein Versuch problemlos und der Code ist weder sicherheitsrelevant noch für irgendeine Art von Produktion relevant, sondern lediglich komplexe mathematische Berechnungen. Daher hat dieser Versuch immer ausgereicht.
In meinem aktuellen Fall wäre es großartig, wenn ich die Protokollierung erneut starten könnte, ohne den Vorgang neu zu starten.
Antwort1
Die Datei bleibt bestehen, solange der tee
Prozess einen offenen Dateideskriptor hat, und es wird weiterhin alles dort protokolliert. Sie können den aktuellen Inhalt wiederherstellen, indem Sie ihn über /proc kopieren:
Suchen Sie die PID des „Tee“-Prozesses.
Verwenden Sie
lsfd -p <PID>
oderlsof -p <PID>
oder ,ls -l /proc/<PID>/fd
um die Dateideskriptornummer zu finden, die der geöffneten Datei entspricht. (Neben dem Dateinamen wird sogar „(gelöscht)“ markiert.)Bei einfachen Programmen wie „tee“ ist die erste geöffnete Datei fast immer FD Nr. 3, daher wird sie
3
auch in allen Beispielen in diesem Beitrag verwendet.Kopieren Sie den Inhalt der Datei in eine neue Datei durch
/proc
:cp /proc/<TEE_PID>/fd/3 old.log
(Symlinks in /proc/PID/fd sind etwas Besonderes – wenn man sie öffnet, wird immer noch die richtige Datei aufgelöst, selbst wenn der Symlink defekt zu sein scheint oder sogar auf etwas verweist, das nicht einmal eine echte Datei ist.)
Es ist auch möglich, „tee“ dazu zu bringen, in eine neue Datei zu schreiben:
Hängen Sie den
gdb
Debugger an den Prozess an:$ sudo gdb -p <TEE_PID>
Dadurch wird „tee“ angehalten. Das Python-Programm wird möglicherweise auch angehalten, wenn es genügend Protokollausgaben erzeugt, um den Pipe-Puffer zu füllen (sonst wird es nicht bemerkt).
Wenn Sie dies noch nicht getan haben, verwenden Sie den /proc-Trick, um die alte Protokolldatei wiederherzustellen (über eine andere Shell, nicht innerhalb von gdb):
$ cp /proc/<TEE_PID>/fd/3 old.log
Auf diese Weisenachgdb angehängt ist (d. h. während „tee“ angehalten ist), können Sie den Verlust von Nachrichten während der Lücke zwischen „cp“ und „open()“ vermeiden.
Verwenden Sie nun gdb, um „tee“ zu veranlassen, die Datei zu schließen und erneut zu öffnen:
(gdb) p (int) close(3) $1 = 0 (gdb) p (int) open("new.log", 01|0100|02000, 0666) $2 = 3 (gdb) q Detach? y
(Die Werte
01|0100|02000
sind gleichO_WRONLY|O_CREAT|O_APPEND
vonfcntl.h, wodurch sich der open()-Aufruf wie der>>
Shell-Operator verhält.)In einfachen Fällen wie „tee“ ist es äußerst unwahrscheinlich, dass open() Ihnen einen anderen Dateideskriptor als den ursprünglichen #3 liefert, da dies der niedrigste freie FD ist. In einigen Situationen mit komplexeren Programmen (wenn eine Nummerierungslücke besteht) kann es jedoch erforderlich sein, aufzurufen
dup2($2, 3)
undclose($2)
die neu geöffnete Datei manuell auf den gewünschten FD zu verschieben.Die alte Datei ist nun vollständig verschwunden (da sie entfernt wurdeUndder letzte Datei-Handle wurde geschlossen), aber „tee“ schreibt in die neue Datei, ohne etwas zu bemerken.
Hinweis: Anstatt eine neue Datei zu öffnen,MaiEs wäre möglich, linkat()
damit die ursprüngliche Protokolldatei ohne Unterbrechung wiederherzustellen, aber ich habe das noch nicht getestet. (Bearbeiten: Leider funktioniert dies laut linkat()-Dokumentation speziell bei Dateien nicht, deren Verknüpfung vollständig aufgehoben wurde.)