意外刪除運行進程`python Something.py 2>&1 | 的日誌文件三通.log`。有沒有辦法仍然將輸出保存在 tmux 窗格上?

意外刪除運行進程`python Something.py 2>&1 | 的日誌文件三通.log`。有沒有辦法仍然將輸出保存在 tmux 窗格上?

不小心刪除了正在運行的進程的日誌檔案python something.py 2>&1 | tee .log。該腳本在 zsh 上的 tmux 窗格中運行。該進程仍在運行,但不記錄日誌。輸出本身溢出 tmux-scrollback-buffer。我可以以某種方式(管理員/sudo 權限)再次啟動日誌記錄過程而不重新啟動該過程嗎?

通常,我的嘗試不會出現問題,程式碼與安全或任何類型的生產無關,而只是複雜的數學計算。所以,這樣的嘗試始終是足夠的。

在我目前的情況下,如果我可以在不重新啟動進程的情況下再次開始日誌記錄,那就太好了。

答案1

只要進程tee持有開啟的檔案描述符,檔案就會繼續存在,並且所有內容仍然記錄在那裡。您可以透過 /proc 複製它們來恢復其當前內容:

  1. 尋找“tee”進程的 PID。

  2. 使用lsfd -p <PID>lsof -p <PID>ls -l /proc/<PID>/fd尋找與開啟的文件對應的文件描述符號。 (它甚至會在文件名旁邊標記為“(已刪除)”。)

    對於諸如“tee”之類的簡單程序,打開的第一個檔案幾乎總是 FD #3,因此本文中的所有範例3也將使用。

  3. 透過以下方式將文件的內容複製到新文件/proc

    cp /proc/<TEE_PID>/fd/3 old.log
    

    (/proc/PID/fd 中的符號連結很特殊 - 打開它們仍然可以解析為正確的文件,即使符號連結看起來已損壞,或者即使它指向的東西甚至不是真正的文件。)

也可以讓 'tee' 開始寫入新檔案:

  1. gdb偵錯器附加到進程:

    $ sudo gdb -p <TEE_PID>
    

    這將暫停“tee”。如果 Python 程式產生足夠的日誌輸出來填充管道緩衝區,則它也可能會暫停(否則它不會注意到)。

  2. 如果您還沒有 – 使用 /proc 技巧來還原舊的日誌檔案(透過另一個 shell,而不是從 gdb 內):

    $ cp /proc/<TEE_PID>/fd/3 old.log
    

    透過做這個gdb 已附加(即當「tee」掛起時),您可以避免在「cp」和 open() 之間的間隙遺失訊息。

  3. 現在使用 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_APPENDfcntl.h,這使得 open() 呼叫的行為類似於>>shell 操作子。

    對於諸如“tee”之類的簡單情況,open() 極不可能為您提供原始#3 之外的任何其他檔案描述符,因為這是最低的可用 FD。但在某些情況下,程式更複雜(如果存在編號間隙),可能需要呼叫dup2($2, 3)close($2)手動將新開啟的檔案移至所需的 FD。

  4. 舊文件現在將完全消失(因為它已被刪除最後一個檔案句柄已關閉),但「tee」將寫入新檔案而不會注意到任何事情。

注意:它不是開啟一個新文件,而是可能可以用來linkat()在不中斷任何事情的情況下使原始日誌檔案存在,但我還沒有對此進行測試。 (編輯:不幸的是,根據 linkat() 文檔,這對於完全取消連結的文件不起作用。)

相關內容