Rocky Alma 哪些更新需要重新開機?
dnf update 後,舊 kernel 與函式庫可能仍在執行。使用 needs-restarting 判斷是否需要重新開機,或只需重新啟動服務。
Rocky Linux 和 AlmaLinux 的哪些更新需要重新開機
在 Rocky Linux 和 AlmaLinux 上,dnf update 會將新檔案寫入磁碟,然後停止後續處理。已開機的 kernel 會繼續執行。已開啟某個函式庫的程序,會繼續使用它開啟的副本,因為 Linux 會讓舊檔案留在磁碟上,直到最後一個持有該檔案的程序結束。因此,機器可能顯示沒有可用更新,但實際上仍在執行這些更新所取代的程式碼。這兩個發行版的行為沒有差異,因為它們都重新建置相同的 Red Hat 來源套件;而 Rocky 與 Alma 之間的選擇 取決於相容性承諾與 CPU 支援,而不是本節會看到的任何內容。以下命令也與 CentOS 主機使用的命令相同,這並非巧合:兩個專案都是在 2020 年 Stream 公告後,作為 CentOS 替代方案建立的。
哪些更新需要重新開機,哪些只需要重新啟動服務,必須由機器本身判斷。可回答這個問題的命令是 needs-restarting。更新可分為 3 個層級。kernel 與一小組核心套件需要完整重新開機。一般函式庫更新需要重新啟動使用它們的服務。其他更新在 RPM 完成後便已套用。
安裝 needs-restarting
needs-restarting 是 DNF 外掛程式。此外掛程式包含在 dnf-plugins-core 中,而大多數 Rocky 和 Alma 安裝通常已預先安裝該套件。/usr/bin/needs-restarting 指令是包含在 dnf-utils 中的小型包裝程式。
sudo dnf install -y dnf-utils
needs-restarting --help這兩種寫法會執行相同的程式碼,因為該包裝程式會呼叫 DNF 子命令:
needs-restarting -r
dnf needs-restarting -r這兩個套件都來自發行版本身的套件庫,因此不需要啟用 EPEL 或 CRB 套件庫。
在 Rocky Linux 10 和 AlmaLinux 10 系列中,dnf 是 DNF 5,而 needs-restarting 是其內建指令之一,來自 dnf5-plugins 套件。在這些版本中,不加選項執行 dnf needs-restarting 即可直接取得是否需要重新開機的結果。-r 仍受支援,手冊指出它不會產生任何作用,僅為了讓 DNF 4 指令碼維持相容性而保留。
第 1 層:需要重新開機的更新
先執行重新開機檢查。它只會讀取 RPM 資料庫與系統開機時間,不會執行其他操作,因此速度很快,也不需要 root。
needs-restarting -r自上次開機後沒有重要變更時,它會輸出兩行:
No core libraries or services have been updated since boot-up.
Reboot should not be necessary.發生變更時,它會先輸出 Core libraries or services have been updated since boot-up:,接著列出找到的套件名稱,最後輸出:
Reboot is required to fully utilize these updates.
More information: https://access.redhat.com/solutions/27943結束碼會傳達相同的結果:不需要重新開機時為 0,需要重新開機時為 1。這就是腳本要依據的部分。
if ! needs-restarting -r >/dev/null; then
logger -t updates "reboot pending on $(hostname -s)"
fi這裡的結束碼 1 是正常結果,不代表失敗。在 set -e 下,未加防護的 needs-restarting -r 會讓腳本在該行結束,因此上面的範例會將它包在 if 中。
會觸發需要重新開機結果的套件,是 plugin 內部硬式編碼的簡短清單。目前版本包含 kernel、kernel-core、kernel-rt、glibc、linux-firmware、systemd、dbus、dbus-broker、dbus-daemon 和 microcode_ctl。較舊的 plugin 組建包含的清單略短,因此請檢查實際版本,不要直接假設。
清單中的每個項目都有明確原因。新的 kernel 套件只會將檔案寫入 /boot 和 /lib/modules,而執行中的 kernel 無法在自身執行期間被替換,因此必須重新開機後才會生效。系統上的每個程序都會連結 glibc,也就是說,「重新啟動受影響的服務」還包括重新啟動 PID 1;重新開機是較安全的做法。dbus 和 dbus-broker 承載系統上的所有用戶端連線,因此在執行中的機器上停止該 bus,會中斷目前與其通訊的用戶端。linux-firmware 和 microcode_ctl 會在開機時載入;在 VPS 上,microcode 通常不會造成可觀察的變化,因為實體 CPU 由 hypervisor 主機管理。
你可以加入自訂套件。/etc/dnf/plugins/needs-restarting.d/ 下的任何 .conf 檔案都會被讀取為套件名稱清單,每行一個名稱;這些名稱會加入需要重新開機的清單。
echo 'openssl-libs' | sudo tee /etc/dnf/plugins/needs-restarting.d/openssl.conf這是政策選擇,不是修正措施。它表示:「TLS library 變更時,我寧可重新開機,也不想逐一找出所有已載入該 library 的服務。」
實際上是從哪裡判斷需要重新開機
needs-restarting -r 不會比較目前執行中的 kernel 版本與最新安裝的 kernel。它比較的是時間戳記。對於核心清單中的每個套件,它會讀取 RPM 安裝時間,並與系統開機時間比較。如果核心套件是在上次開機後安裝,結果就是「需要重新開機」。如果可以使用,開機時間會透過 D-Bus 取自 systemd 的 UnitsLoadStartTimestamp;否則會取 /proc/1 的修改時間與 /proc/stat 中的 btime 欄位兩者較晚者。
這個機制有一項值得注意的結果。如果你安裝 kernel、重新開機,卻因為開機預設值被固定而回到較舊的 kernel,安裝時間現在早於開機時間,needs-restarting -r 就會停止提示。它正確回答了自己的問題,但不是你提出的問題。請另外檢查 kernel。
uname -r
rpm -q --last kernel
sudo grubby --default-kernel第一個命令會顯示目前正在執行的內容。rpm -q --last kernel 的第一行是最近安裝的 kernel。grubby --default-kernel 會顯示 bootloader 下次將選取的項目。如果這三者不一致,請先修正開機預設值,再重新開機無法透過主控台連線的機器。
需要重新啟動服務的更新
當 RPM 取代共用函式庫時,會解除舊檔案的連結並寫入新檔案。已經對舊檔案建立記憶體對映的程序,會讓舊 inode 繼續存在,並持續執行舊程式碼。openssl-libs 是最重要的情況:libcrypto 中的修正,必須等 Web 伺服器重新啟動後才會套用。
sudo needs-restarting -s這會列出自身檔案,或相依性檔案,在服務啟動後曾更新的 systemd 服務。請使用 sudo。未具備 root 權限時,此工具只能讀取自己程序的 /proc 項目,因此會悄悄漏報,讓短清單看起來像是好消息。
sudo needs-restarting
sudo needs-restarting --exclude-services第一個命令會列印每個受影響程序的 PID 和命令列。第二個命令會排除 systemd 服務已涵蓋的程序,留下登入 shell、tmux 工作階段、cron 工作,以及你手動啟動的程序。這些程序都不會自行重新啟動。
如果清單中的服務同時屬於需要重新開機層級的套件,工具會在其上方列印 Warning: The following services should not be restarted but require a reboot:。請依字面理解,改為重新開機。
其餘服務請一次重新啟動一個,並在處理下一個服務前逐一確認。
sudo systemctl restart nginx
systemctl status nginx不要將清單直接傳給 systemctl restart。原因是你自己的 SSH 工作階段。在 RHEL 系列中,sshd.service 隨 KillMode=process 一起提供,因此重新啟動它時會向監聽中的 daemon 發送訊號,而不會影響各個連線程序,開啟中的工作階段也能繼續存在。請使用 systemctl cat sshd | grep KillMode 在自己的主機上確認這一點;第一次操作時,無論如何都應保持第二個工作階段開啟。
不使用 DNF 也能找出相同的程序。當你需要查看相關檔案路徑時,這種方式很實用:
sudo dnf install -y lsof
sudo lsof -n +c 0 2>/dev/null | grep -w DELDEL 表示檔案已從磁碟刪除,但仍有程序對其建立記憶體對映。操作前請先讀取路徑。已刪除的暫存檔案和記憶體支援的檔案也會出現在這裡;這些情況都不是重新啟動任何服務的理由。
第 3 層:其他所有項目
大多數更新都屬於這一層,且不需要其他處理。某個套件的檔案只有在指令啟動時才會讀取,例如 curl、tar、vim 或 dnf 本身;RPM 完成後,這類套件就已完整套用,因為下次執行時會讀取新的二進位檔。設定檔、指令碼、文件與資料套件也是相同情況。needs-restarting 不會提及其中任何項目;這種沒有輸出的情況是正確結果,不代表漏偵測。
這一層唯一需要注意的是執行時間。更新前已啟動的程序會持續使用舊的可執行檔,直到程序結束,不論該套件多麼單純。這正是 sudo needs-restarting --exclude-services 的用途。
為什麼使用 dnf-automatic 的機器可能數週都帶著尚未套用的修正
這正是三個層級不再只是細節的地方。使用 dnf-automatic 自動更新會依排程安裝套件,而 reboot 中的預設 /etc/dnf/automatic.conf 設定為 never。搭配 apply_updates = yes 和 reboot = never 時,機器可以在 6 週內安裝 6 次 kernel 更新和一個 glibc 修正,卻仍使用第 0 週開機時載入的 kernel 與 C library。更新日誌看起來完全正常,但執行中的系統並未套用任何修正。
解法是在 /etc/dnf/automatic.conf 中加入 3 行:
[commands]
upgrade_type = security
apply_updates = yes
reboot = when-needed
reboot_command = "shutdown -r +5 'Rebooting after applying package updates'"reboot 接受 never、when-changed 和 when-needed。never 是預設值,所有決定都由你處理。when-changed 會在任何變更套件的交易完成後重新開機,作法直接但結果可預期。when-needed 會詢問 DNF 剛套用的交易是否需要重新開機,因此僅更新 userspace 的夜間更新不會觸發重新開機。reboot_command 是實際執行的項目,預設會提前 5 分鐘通知已登入的使用者。設定 random_sleep 和計時器的排程,讓重新開機落在你能監看機器恢復運作的時段內。
使用 systemctl list-timers 'dnf-*' 檢查你啟用的 unit。dnf-automatic 會提供數個變體,而且它們的行為不完全相同,因此只查看設定檔無法判斷實際執行的項目。
排程執行完成後,直接向機器查詢,不要只看日誌:
needs-restarting -r; echo "exit: $?"
uname -r
rpm -q --last kernel | head -1如果無法安排重新開機,VPS 的 live kernel patching 是另一種做法。它可以在不重新開機的情況下,將特定 kernel 修正套用至執行中的 kernel。它只涵蓋部分 kernel 問題,也無法處理 glibc 或你的服務,因此應將它視為延後重新開機的方式,而不是完全停止重新開機。需要重新開機時,請有意識地執行,並保持登入直到機器回應,因為 kernel 更新是機器無法恢復運作的最常見原因。若要在沒有 console 存取權的情況下重新開機主機,請先閱讀VPS 在 kernel 更新後無法開機時的處理方式,並將重新開機檢查納入定期伺服器維護檢查清單,避免只有在發生事件後才想起這項工作。
Ubuntu 與 Debian 上的相同作業
混合式伺服器環境需要使用相應的做法。在 Ubuntu 與 Debian 上,重新開機旗標是檔案,而不是命令:套件指令碼會建立 /run/reboot-required,而 /run/reboot-required.pkgs 會列出要求建立該旗標的套件,因此 [ -f /run/reboot-required ] 就是 needs-restarting -r 的直接等效做法。較舊的文件會寫成 /var/run/reboot-required;這是相同的檔案,因為 /var/run 是指向 /run 的 symbolic link。服務端則是 needrestart;近期的 Ubuntu Server 版本預設會安裝此服務。它會在 apt upgrade 執行,也可以單獨執行 sudo needrestart -r l,列出需要重新啟動的項目,但不會實際變更任何內容。自動更新的缺口在這些系統上相同,修正方式也相同:Ubuntu 上的 unattended-upgrades 會在 /etc/apt/apt.conf.d/50unattended-upgrades 中使用 Unattended-Upgrade::Automatic-Reboot "true"; 與 Unattended-Upgrade::Automatic-Reboot-Time "02:00";。
失敗模式與可觀察到的現象
needs-restarting: command not found表示尚未安裝dnf-utils。請安裝它,或改為呼叫dnf needs-restarting;只要存在dnf-plugins-core,即可使用。- 指令碼在重新開機檢查處停止,且未顯示錯誤訊息,表示
set -e傳回了結束代碼 1。此代碼表示「需要重新開機」,因此應依此代碼分支處理,不要讓它直接終止指令碼。 - 程式庫更新後,
needs-restarting -s通常沒有任何輸出,表示執行時未加上sudo。沒有 root 權限時,它只能看到目前使用者自己的程序。 needs-restarting -r顯示不需要重新開機,但uname -r顯示舊版本,表示目前啟動的是較舊的核心。此檢查會比較安裝時間與開機時間,而這兩個時間目前都已早於更新時間。請查看grubby --default-kernel。- 服務重新啟動後,幾分鐘內又在下一次執行時出現,通常表示有其他元件正在重新啟動它,或該 unit 未能恢復執行。再次重新啟動前,請先查看該 unit 的
systemctl status。
FAQ
dnf update 會在 Rocky Linux 上重新啟動服務嗎?
一般不會。交易程序會寫入檔案,然後結束。部分套件在升級時確實包含會重新啟動自身服務的 RPM scriptlet,因此行為取決於個別套件,不是整個系統的保證。應以 sudo needs-restarting -s 為準:它會列出服務啟動後,其檔案或相依套件檔案有所變更的服務,不論 scriptlet 執行了什麼操作。
為什麼安裝較新的 kernel 後,needs-restarting -r 仍顯示不需要重新開機?
因為它會比較少數核心套件的 RPM 安裝時間與系統開機時間。它不會比較目前執行中的 kernel 版本與最新安裝的版本。如果你安裝 kernel 後重新開機,但因為 bootloader 的預設值指向較舊的 kernel,導致系統仍使用舊版 kernel,安裝時間就會早於開機時間,因此檢查不會提出警示。執行 uname -r、rpm -q --last kernel 和 sudo grubby --default-kernel,即可查看實際狀況。
哪些套件會在 Rocky 和 Alma 上觸發重新開機提示?
這取決於 plugin 內硬式編碼的清單。目前版本包含 kernel、kernel-core、kernel-rt、glibc、linux-firmware、systemd、dbus、dbus-broker、dbus-daemon 和 microcode_ctl。你可以擴充這份清單:將包含套件名稱的 .conf 檔案放入 /etc/dnf/plugins/needs-restarting.d/,每行列出一個套件名稱。這些名稱也會納入重新開機判定。
dnf-automatic 能自行重新啟動伺服器嗎?
可以。在 /etc/dnf/automatic.conf 的 [commands] 區段中設定 reboot = when-needed,只有套用的交易程序需要重新開機時才會執行重新開機。when-changed 會在任何套件變更後重新開機,而 never 是預設值。reboot_command 控制執行方式,其預設值會先向已登入的使用者發出 5 分鐘前的警告。只有在你能夠復原該機器的開機流程時才啟用此功能,因為無法透過主控台存取的 VPS 若無人值守地重新開機,可能會進入無法復原的故障狀態。
needs-restarting 能偵測容器內的程序嗎?
無法有效偵測。它會將執行中的程序與主機的 RPM 資料庫比對,而容器映像檔內的套件不在該資料庫中,因此映像檔中內建的過期函式庫不會顯示。請重新建置映像檔並重新部署。主機端仍然重要:容器 runtime 與其共用的 kernel 都是主機套件,因此這些項目仍會被顯示。