
不小心刪除了正在運行的進程的日誌檔案python something.py 2>&1 | tee .log
。該腳本在 zsh 上的 tmux 窗格中運行。該進程仍在運行,但不記錄日誌。輸出本身溢出 tmux-scrollback-buffer。我可以以某種方式(管理員/sudo 權限)再次啟動日誌記錄過程而不重新啟動該過程嗎?
通常,我的嘗試不會出現問題,程式碼與安全或任何類型的生產無關,而只是複雜的數學計算。所以,這樣的嘗試始終是足夠的。
在我目前的情況下,如果我可以在不重新啟動進程的情況下再次開始日誌記錄,那就太好了。
答案1
只要進程tee
持有開啟的檔案描述符,檔案就會繼續存在,並且所有內容仍然記錄在那裡。您可以透過 /proc 複製它們來恢復其當前內容:
尋找“tee”進程的 PID。
使用
lsfd -p <PID>
或lsof -p <PID>
或ls -l /proc/<PID>/fd
尋找與開啟的文件對應的文件描述符號。 (它甚至會在文件名旁邊標記為“(已刪除)”。)對於諸如“tee”之類的簡單程序,打開的第一個檔案幾乎總是 FD #3,因此本文中的所有範例
3
也將使用。透過以下方式將文件的內容複製到新文件
/proc
:cp /proc/<TEE_PID>/fd/3 old.log
(/proc/PID/fd 中的符號連結很特殊 - 打開它們仍然可以解析為正確的文件,即使符號連結看起來已損壞,或者即使它指向的東西甚至不是真正的文件。)
也可以讓 'tee' 開始寫入新檔案:
將
gdb
偵錯器附加到進程:$ sudo gdb -p <TEE_PID>
這將暫停“tee”。如果 Python 程式產生足夠的日誌輸出來填充管道緩衝區,則它也可能會暫停(否則它不會注意到)。
如果您還沒有 – 使用 /proc 技巧來還原舊的日誌檔案(透過另一個 shell,而不是從 gdb 內):
$ cp /proc/<TEE_PID>/fd/3 old.log
透過做這個後gdb 已附加(即當「tee」掛起時),您可以避免在「cp」和 open() 之間的間隙遺失訊息。
現在使用 gdb 關閉 'tee' 並重新開啟檔案:
(gdb) p (int) close(3) $1 = 0 (gdb) p (int) open("new.log", 01|0100|02000, 0666) $2 = 3 (gdb) q Detach? y
(這些值
01|0100|02000
等於O_WRONLY|O_CREAT|O_APPEND
fcntl.h,這使得 open() 呼叫的行為類似於>>
shell 操作子。對於諸如“tee”之類的簡單情況,open() 極不可能為您提供原始#3 之外的任何其他檔案描述符,因為這是最低的可用 FD。但在某些情況下,程式更複雜(如果存在編號間隙),可能需要呼叫
dup2($2, 3)
並close($2)
手動將新開啟的檔案移至所需的 FD。舊文件現在將完全消失(因為它已被刪除和最後一個檔案句柄已關閉),但「tee」將寫入新檔案而不會注意到任何事情。
注意:它不是開啟一個新文件,而是可能可以用來linkat()
在不中斷任何事情的情況下使原始日誌檔案存在,但我還沒有對此進行測試。 (編輯:不幸的是,根據 linkat() 文檔,這對於完全取消連結的文件不起作用。)