Filesystems

如何升級共享庫而不崩潰?

  • March 18, 2014

在這裡它說您可以重寫一個執行檔並且該程序將執行得很好 - 當一個程序重新啟動時它將被重新讀取。

但是,當我在程序執行時(使用 scp,從開發伺服器到測試伺服器)嘗試替換二進製文件時,它會顯示“文件忙”。如果我替換一個共享庫文件 (*.so),連結它的所有程序都會崩潰。

為什麼這樣?我錯過了什麼嗎?如何在不停止/崩潰程序的情況下替換二進製文件?

正如為什麼軟體包即使在升級時也能正常執行?, 鎖放在 inode 而不是文件名上。當您載入並執行二進製文件時,該文件被標記為忙 - 這就是您嘗試寫入時收到 ETXTBSY(文件忙)錯誤的原因。

現在,對於共享庫,情況略有不同:庫將記憶體映射到程序的地址空間,使用mmap(). 儘管MAP_DENYWRITE可以指定,但至少 Linux 上的 Glibc 會默默地忽略它(根據手冊頁,請隨時查看原始碼) - 檢查這個執行緒。因此,您實際上可以編寫文件,並且由於它是記憶體映射的,因此幾乎可以立即看到任何更改 - 這意味著如果您足夠努力,您可以 通過覆蓋庫來設法使您的機器變磚。

因此,正確的更新方法是:

  1. 刪除文件,這會從文件系統中刪除對數據的引用,以便任何可能想要使用它的新生成的應用程序都無法訪問它,同時保持已經打開(或映射)它的任何人都可以訪問數據;
  2. 創建一個包含更新內容的新文件。

新創建的程序將使用更新的內容,正在執行的應用程序將訪問舊版本。這是任何理智的包管理實用程序所做的。請注意,它並非完全沒有任何危險——例如dlsym(),如果庫的 API 無聲地更改,動態載入程式碼的應用程序(使用和朋友)將遇到麻煩。

如果您想真正安全,請關閉系統,從另一個作業系統實例掛載文件系統,更新並再次啟動更新的系統。

引用自:https://unix.stackexchange.com/questions/74165