Ubuntu 24.04 升級 26.04 失敗如何修復
升級從 Ubuntu 24.04 到 26.04 中途停止?本文說明如何重新連線 screen、修復 dpkg、處理切換一半的套件來源,並判斷何時應還原快照。
Ubuntu 升級中途失敗:先查看症狀
從 24.04 升級 Ubuntu 版本至 26.04 失敗後,伺服器會處於 4 種狀態之一,而每種狀態都有不同的修復方式。升級程式可能仍在某個失去連線的 screen 工作階段中執行。dpkg 可能在某個套件尚未完成設定時遭到終止,因此 apt 現在拒絕任何安裝、移除或升級套件的操作,即使 apt update 及 apt show 等唯讀命令仍可執行。apt 來源可能已指定 26.04,但已安裝的套件仍是 24.04。伺服器也可能完全無法開機。執行任何操作前,先確認屬於哪一種狀態,因為針對其中一種狀態採取的修復方式,可能使另一種狀態更加嚴重。
以下規則適用於全部 4 種狀態。在確認 dpkg 的狀態前,不要重新開機。在套件交換過程中重新開機,可能會把原本可修復的 dpkg 中斷,變成本指南後段所述的無法開機狀態。此外,第一個 apt 或 dpkg 程序可能仍在執行時,不要啟動第二個 apt 或 dpkg 程序,因為兩個程序同時寫入套件資料庫,會導致資料庫損毀。
本指南假設你已遵循24.04 至 26.04 的升級指南,並在開始前建立 snapshot。若沒有,請留意開機區段,因為 snapshot 是最嚴重情況的復原方式。
升級作業仍在執行嗎?
許多被回報為失敗的升級其實仍在執行。SSH 工作階段中斷、終端機畫面變空白,但升級程式仍在沒有你的情況下繼續執行。
do-release-upgrade 就是為此設計的。它以文字介面執行時,也就是伺服器上的執行方式,會將自身包裝在 GNU screen 工作階段中。因此,即使啟動升級的終端機遺失,升級仍可繼續。另一方面,當它偵測到自己是從 SSH 工作階段啟動時,會提供在另一個埠上啟動第二個 sshd 的選項,預設為 1022。如此一來,即使主要 SSH daemon 在交換套件期間損壞,你仍可登入。這兩點現在都很重要。
透過 SSH 重新連線,然後尋找 screen 工作階段。升級程式是在 sudo 下執行,因此其 screen 工作階段屬於 root;以你自己的使用者直接執行 screen -ls 不會列出該工作階段。
sudo screen -lsscreen -ls 會標示每個工作階段目前是已附加或已分離。如果列出工作階段,請重新附加到該工作階段。如果它仍標示為已附加,原因可能是已中斷的 SSH 連線尚未釋放工作階段。此時 -d 會先分離這個失效的附加連線。
sudo screen -d -r如果列出多個工作階段,請將 screen -ls 中的工作階段名稱放在 -r 後面。不要假設 sudo do-release-upgrade 會替你重新附加。尋找既有 screen 工作階段的程式碼位於升級程式下載的內容中;而在下載任何內容之前,只要發現有套件等待升級,do-release-upgrade 就會結束並顯示「請先為你的版本安裝所有可用更新,再進行升級」。這不包括分階段推出的更新。這正是系統已進行一半套件交換時的狀態。重新附加後,你會回到仍在執行的升級作業中。升級通常會停在詢問設定檔變更或服務重新啟動的提示上。請回答提示,讓升級完成。
如果你依照升級指南的建議,在 tmux 中啟動升級,請先使用 tmux attach 重新附加 tmux。screen 工作階段是在該 tmux 窗格內執行,因此你會直接看到升級進度。如果窗格中只有 shell 提示字元,表示升級程式已不再於該處執行,接下來請檢查 sudo screen -ls。
如果主要 SSH 埠拒絕連線,請嘗試備援埠:ssh -p 1022 user@host。該 daemon 只會在升級期間存在。因此,如果兩個埠都無法登入,請改用供應商提供的主控台。在主控台中,sudo ss -ltnp 可顯示 sshd 程序正在監聽的埠,而 sudo ufw status 可確認防火牆是否允許備援埠的流量通過。
如果不存在 screen 工作階段,主控台上也沒有任何等待中的提示,表示升級確實已停止。在進行任何處理前,先確認套件資料庫沒有仍在執行的作業:
ps -eo pid,etime,cmd | grep -iE '[u]pgrade|[d]pkg|[a]pt'結果為空表示 dpkg 處於閒置狀態,你可以繼續修復升級。如果有 dpkg 或 apt 程序執行時間很長,且沒有可重新附加的 screen 工作階段,表示程序可能已掛起。先再等幾分鐘,並檢查主控台是否有無人回答的 debconf 問題,之後才終止程序。當程序仍持有 /var/lib/dpkg/ 或 /var/lib/apt/lists/ 中的鎖定檔時,絕不要刪除這些檔案。鎖定是防止兩個寫入程序損壞套件資料庫的唯一機制。
dpkg 中斷,apt 拒絕執行
當 dpkg 在解開套件與執行其設定指令碼之間被終止時,該套件會被標記為尚未完成,並在 /var/lib/dpkg/updates/ 下的日誌中留下未完成的項目。所有需要取得 dpkg 鎖定的 apt 指令,也就是會安裝、移除或升級套件的指令,都會先檢查該日誌,然後以 dpkg was interrupted, you must manually run 'sudo dpkg --configure -a' to correct the problem. 停止。從不取得該鎖定的指令,例如 apt update、apt list、apt show 和 apt-cache,仍可正常執行,因此你仍能查看系統狀態。無論 apt 顯示其他什麼訊息,第一步都相同。
sudo dpkg --configure -a這會完成所有已解開但尚未設定之套件的設定步驟。它會依相依性順序執行維護者指令碼。在升級進行到一半的系統上,這可能需要很長時間,因此請等待它完成。若程序在某個套件上停止,會顯示套件名稱及失敗的指令碼。請記下該名稱。這就是中止升級的套件,下一節會說明如何讀取其錯誤訊息。
接著讓 apt 修復中斷留下的未滿足相依性,因為部分套件已升級,但其相依套件尚未升級。
sudo apt --fix-broken install接著完成升級工具原本正在執行的升級:
sudo apt update
sudo apt full-upgrade請使用 full-upgrade,不要使用 upgrade,因為版本升級會移除套件,而一般的 upgrade 拒絕移除任何套件。確認前請先閱讀 apt 顯示的摘要。少量移除項目屬於正常情況。若清單要移除 ubuntu-server、systemd、openssh-server 或 kernel 套件,就不正常;此時應回答否,先查明 apt 為何要移除這些套件,再繼續操作。
進行其他操作前,先確認結果:
sudo dpkg --audit
sudo apt-get checkdpkg --audit 會列出所有仍處於損壞狀態的套件,apt-get check 會回報未滿足的相依性。兩者都應不輸出任何內容。確認無誤後,執行 sudo apt autoremove,移除不再被任何套件需要、且由系統自動安裝的相依套件(標記為手動安裝的套件會保留,即使目前沒有任何套件使用它們),接著以 cat /etc/os-release 確認版本,再執行 sudo update-initramfs -u -k all 和 sudo update-grub,最後才重新開機。
如何讀取 /var/log/dist-upgrade,找出中止升級的套件
升級工具會將所有內容寫入 /var/log/dist-upgrade/。如果你執行過不只一次,它會將先前嘗試的日誌移至以時間戳記命名的子目錄,因此請先檢查 ls -la /var/log/dist-upgrade/,再讀取與失敗執行相符的目錄。
main.log 是升級工具自己的執行記錄。它會記錄執行所處的階段,以及它對套件來源的判斷。如果升級工具本身當機,這裡也會有 Python traceback。請從檔案末端開始讀取:最後幾行會指出它停止時所處的階段;如果那裡有 traceback,表示是工具失敗,而不是套件失敗。
apt.log 包含相依性解析器的判斷過程。內容很詳細;當 apt 完全拒絕計算升級時,這份檔案才特別重要,因為這表示在任何套件被處理前就已經失敗。如果升級已進行到安裝套件,通常可以略過它。
apt-term.log 是查找套件失敗時應讀取的檔案。它會保存升級期間 dpkg 的終端輸出,也就是原本會直接顯示在畫面上的相同內容。檔案結尾前最後提到的套件,就是升級停止時正在處理的套件;如果維護者指令碼失敗,dpkg 對該指令碼的錯誤回報就在那裡,其上方緊接著是指令碼本身的錯誤。
sudo tail -n 60 /var/log/dist-upgrade/apt-term.log
sudo grep -in 'error' /var/log/dist-upgrade/apt-term.log | tail請與 /var/log/dpkg.log 交叉比對。該檔案會記錄 dpkg 執行的狀態變更與動作,並為每項動作附上時間戳記。tail -n 30 /var/log/dpkg.log 會顯示 dpkg 最後處理的套件,以及當時對它執行的動作。只有在失敗後尚未有其他程序執行 dpkg 時,這才會與前一份記錄得到相同答案。執行 dpkg --configure -a 或 apt --fix-broken install 後,它們的項目會出現在檔案末端,因此請回到升級停止時間的時間戳記所在行。
在伺服器上,這個階段的大多數失敗都源自幾個常見原因。套件在 postinst 中重新啟動的服務,可能因為你自訂的設定檔而無法啟動;對該服務執行 systemctl status 加上 journalctl -xeu,即可找出它不接受的設定行。磁碟空間可能已用盡,最常見的是 /boot 存放舊 kernel,或 /var 存放 apt 的套件快取;df -h / /boot /var 會顯示此狀況。即使 apt 已卡住,sudo apt clean 仍可清空快取;du 顯示未滿,但磁碟回報已滿則有另一套說明。升級工具停用的第三方套件庫中,某個套件可能相依於 26.04 不再提供的函式庫。已保留的套件(apt-mark showhold)可能阻止某項相依性套件升級。修正原因後,再次執行 sudo dpkg --configure -a。它會從停止的位置繼續。
如果無論如何都無法設定某個套件,而且沒有重要套件依賴它,請先移除該套件,待升級完成後再重新安裝:
sudo dpkg --remove --force-remove-reinstreq package-name
sudo dpkg --configure -a這項操作只適用於你能明確指出並說明問題的套件。不要對函式庫或 ubuntu-server 相依性鏈中的任何項目使用,因為強制移除會略過原本用來告知你哪些項目也會損壞的檢查。
來源已切換但套件未更新
升級程式會在下載任何套件前,先行重寫您的 apt 來源。若在此階段中斷,來源檔會顯示 26.04,但已安裝的套件仍處於混合狀態。這種混合狀態會導致工具判斷錯誤,這也是為什麼 do-release-upgrade 現在可能堅持沒有新版本可用的原因。
請比較兩處描述您目前版本資訊的位置。/etc/apt/sources.list.d/ubuntu.sources 是 24.04 引入的 deb822 格式來源檔,其 Suites: 行包含發行代號。/etc/os-release 則由 base-files 套件寫入,記載了實際安裝的版本。
grep -E '^(Suites|Components):' /etc/apt/sources.list.d/ubuntu.sources
grep -E '^(VERSION_ID|VERSION_CODENAME)=' /etc/os-release
apt-cache policy base-files有三種組合需要注意。來源檔仍顯示 24.04(代號 noble)且 os-release 顯示 24.04:表示升級程式未通過檢查,請閱讀 main.log 了解停止原因後,再次執行 sudo do-release-upgrade。若有任何 24.04 更新待處理,或 /var/run/reboot-required.pkgs 包含 libc6、linux-base 或 linux-image 套件,升級程式將拒絕啟動,請先執行 sudo apt full-upgrade 並在該檔案要求時重新開機。來源檔顯示 26.04 代號但 os-release 顯示 24.04:表示套件交換已開始但中斷,請執行前一節以 apt full-upgrade 結尾的 dpkg 修復程序來完成。在此狀態下請勿重新執行升級程式;因為有 26.04 套件等待處理,它會停止並要求您先安裝所有可用更新。來源檔顯示 26.04 且 os-release 顯示 26.04:表示 base-files 是已完成更新的套件之一,系統現在自稱為 26.04,即使大部分內容並非如此。
最後一種組合是陷阱。do-release-upgrade 會根據 os-release 攜帶的相同資訊來判斷您的版本。如果該檔案已顯示 26.04,接下來的報告取決於 /etc/update-manager/release-upgrades 中的 Prompt= 行。在 Prompt=lts 設定下(26.04 的預設值),工具會尋找比 26.04 更新的 LTS 版本,若找不到,就會回報沒有新版本可用。在 Prompt=normal 設定下,Canonical 關於 26.10 的公告(2026 年 10 月 15 日發布)指出 26.04 的使用者將會收到 26.10 的升級提示。Ubuntu 的升級中繼資料在 2026 年 10 月 24 日檢查時尚未列出 26.10,因此該工具當天仍回報沒有新版本;一旦 26.10 被列入,它會找到 26.10,然後因為仍有 24.04 的套件待更新,而停止並顯示「請在升級前安裝您版本的所有可用更新」。無論如何,該工具是在回答關於 os-release 的問題,而 os-release 的資訊是錯誤的。請停止使用升級程式,改用 apt 完成作業:執行 sudo apt update,接著執行 sudo apt full-upgrade,這會升級所有仍處於 24.04 版本的套件(保留狀態的套件除外,可透過 apt-mark showhold 列出),並可能移除部分套件,請務必閱讀摘要,最後執行 sudo apt autoremove。若 os-release 仍顯示 24.04,則值得排除 do-release-upgrade 回報沒有新版本的其他原因。LTS 提示必須等待第一個點發行版本(point release)的限制已不再適用:Ubuntu 的 LTS 升級中繼資料在 2026 年 10 月 24 日檢查時,已將 26.04.1 列為支援版本。
升級程式也會停用 /etc/apt/sources.list.d/ 下的第三方來源,並保留每個已變更檔案的備份,在原始名稱後加上後綴。請執行 ls -la /etc/apt/sources.list.d/ 並將每個原始檔案與其備份進行 diff 比對,以確認其變更內容。在 Ubuntu 套件恢復一致前,請保持第三方來源停用;確認供應商已發布 26.04 專用套件後,再逐一重新啟用。若 apt update 顯示來源設定重複的錯誤,表示舊的 sources.list 項目與新的 ubuntu.sources 項目描述了相同的套件庫,deb822 重複來源錯誤 一節說明了應移除哪一個。
升級後伺服器無法開機
重新開機時,未完成的升級可能會造成問題。在 VPS 上,常見原因包括安裝 kernel 時未建立 initramfs、從未重新產生 GRUB 設定、某個開機時需要的 unit 尚未完成套件設定,或磁碟在 dpkg 寫入資料時已填滿。
先開啟供應商提供的主控台,再進行其他操作。主控台會顯示開機停止的位置:GRUB 選單、kernel panic、等待回應的檔案系統檢查,或要求輸入 root 密碼的 systemd emergency shell。這項觀察結果會決定下一步。
如果出現 GRUB,請從進階選項子選單啟動先前的 24.04 kernel。舊 kernel 通常會一直保留,直到執行 autoremove 為止。系統使用舊 kernel 啟動後,執行 sudo dpkg --configure -a,並依照上一節完成其餘修復;接著執行 sudo update-initramfs -u -k all 和 sudo update-grub,再重新嘗試啟動新 kernel。復原更新 kernel 後無法開機的 VPS 詳細說明了 GRUB 和 initramfs 相關處理方式。
如果進入 emergency shell,root 檔案系統通常會以唯讀模式掛載。重新掛載後,執行相同的修復程序:
mount -o remount,rw /
dpkg --configure -a如果系統完全未進入 shell,請啟動供應商提供的 rescue image,掛載 VPS 磁碟,然後從 chroot 中進行修復。請使用 lsblk 找出 root 分割區,不要自行猜測名稱。
lsblk
mount /dev/<root-partition> /mnt
for d in dev proc sys run; do mount --bind /$d /mnt/$d; done
chroot /mnt /bin/bash
dpkg --configure -a
apt --fix-broken install
update-initramfs -u -k all
update-grub
exit
reboot在 chroot 中花費一小時之前,請先評估是否應改用 snapshot。你在開始前已建立 snapshot,而多數供應商只需幾分鐘即可還原。接著重新執行升級;在 VPS 上通常不到一小時,且這次你已知道要先修復哪個套件。符合以下任一情況時,還原通常是較快的方式:無法取得主控台或 rescue image、無法判斷是哪個套件中斷升級、卡住的套件不只一個,或伺服器上執行著使用者正在等待的服務。只有在你確定是哪一項設定或元件損壞,且修復只需一個指令時,手動修補才會比較快。
還原前,請先將 /var/log/dist-upgrade/ 複製到伺服器外部;如果只能透過 rescue image 存取,就從 rescue image 執行。還原會刪除這些日誌;如果你沒有找出第一次失敗的原因,第二次嘗試很可能會完全以相同方式失敗。snapshot 能還原及不能還原的內容 值得在依賴 snapshot 前閱讀。snapshot 會將整個磁碟回復到建立當時的狀態,包括建立後寫入的所有資料。這在升級進行期間通常沒有問題,但如果已經過了一週,就可能造成資料遺失。
改為重建系統的 3 個跡象
有些升級問題不值得挽救。還原 snapshot 並重新執行升級的成本很低;但如果失敗原因來自伺服器本身的狀態,第二次執行也會失敗。此時,正確的處理方式是使用全新的 26.04 image,並從 backup 還原資料。出現以下 3 個跡象時,表示你已經遇到這種情況。
第一,dpkg 自己的資料庫已損壞。如果 dpkg --audit 或 apt-get check 完全無法讀取 /var/lib/dpkg/status,而不是回報其中包含損壞的套件,表示已安裝套件的記錄已遺失。Ubuntu 會在 /var/backups/(ls -la /var/backups/dpkg.status*)下保留每日副本,將最新的正常副本換回原位有時可以解決問題。但如果該副本與磁碟上的實際內容不一致,你就只能猜測;之後每次執行 apt 都會建立在這個猜測上。
第二,修復系統所需的工具本身已損壞。如果 apt 或 dpkg 因為 shared library 被移除或只完成部分替換而無法啟動,或 systemd 因為自己的套件只完成部分設定而無法啟動 units,系統就沒有可運作的 package manager 可以修復 package manager。ldd /usr/bin/apt 可用來確認 apt 所需的 libraries 是否完整。你有時可以從 rescue image 的 chroot 環境中 bootstrap 修復系統,但通常這需要的時間比重建系統更久。
第三,損壞套件的清單沒有減少。如果你已經在迴圈中執行 dpkg --configure -a 和 apt --fix-broken install 超過 1 小時,而每次執行都發現新的套件,卻無法清除上一個問題,表示這些問題是在升級前就已存在,並非升級造成。例如,/usr 下的檔案曾由人工修改、套件被 pinned 或 held、第三方 repository 替換了核心 libraries,或先前的升級本身就未完成。全新的 image 不會包含這些問題。將資料還原到新系統所需的時間,也比找出這些問題更短。
只有在資料存放於伺服器以外的位置時,重建系統的成本才低。這就是 snapshot 與 backup 的差異,也是升級指南要求同時準備兩者的原因。
FAQ
若 do-release-upgrade 中斷,我可以再次執行它嗎?
不要直接執行。若升級程式仍在 screen session 中執行,請使用 sudo screen -d -r 重新連線;直接執行第二次 do-release-upgrade 會因為偵測到有待更新的套件而拒絕啟動。若升級程式已終止,請先執行 sudo dpkg --configure -a 與 sudo apt --fix-broken install。若軟體來源列表已指向 26.04,請改用 sudo apt full-upgrade 完成剩餘步驟。若仍指向 24.04,請執行 sudo apt full-upgrade,若 /var/run/reboot-required.pkgs 列出 libc6、linux-base 或核心檔案,請先重新開機,再重新啟動升級程式。若 /etc/update-manager/release-upgrades 中的 Prompt=never 已設定,或 Ubuntu 伺服器回報「目前無法進行版本升級」,升級程式也會拒絕執行。
為什麼升級失敗後,do-release-upgrade 顯示沒有新版本?
因為負責寫入 /etc/os-release 的套件 base-files 在中斷前已完成升級。該工具讀取該檔案後,判定您已處於 26.04 版本,且在預設的 Prompt=lts 設定下,找不到更新的 LTS 版本。若您設定了 Prompt=normal,當 Ubuntu 升級中繼資料列出 26.10 時,它會找到該版本,但隨後會因仍有待更新的套件而拒絕執行。請比較 grep VERSION_ID /etc/os-release 與 grep Suites /etc/apt/sources.list.d/ubuntu.sources,然後使用 sudo apt update && sudo apt full-upgrade 完成升級。
重新開機一台升級到一半的 Ubuntu 伺服器安全嗎?
在 sudo dpkg --audit 回傳空白結果前,請勿重新開機。若在核心已解壓縮但未設定,或 GRUB 未重新產生的狀態下重新開機,原本只需十分鐘即可修復的升級問題,極易演變成需要使用救援映像檔的嚴重故障。請先完成 dpkg 修復與 apt full-upgrade,執行 update-initramfs -u -k all 與 update-grub,確認無誤後再重新開機。
如何找出導致升級中斷的套件?
請查看 /var/log/dist-upgrade/apt-term.log 的結尾,該檔案記錄了 dpkg 的終端機輸出。日誌結尾處顯示的最後一個套件即為中斷時正在處理的項目,而失敗的維護腳本(maintainer script)錯誤訊息通常位於 dpkg 錯誤提示的上方。/var/log/dpkg.log 是第二個參考來源:其時間戳記顯示升級停止的時間點,並標註了相同的套件,但由於中斷後執行的任何 dpkg 指令都會被記錄在後,因此其最後幾行未必準確。若 main.log 的結尾是 Python 追蹤錯誤(traceback),則代表升級程式本身崩潰,並非特定套件的問題。
我應該還原快照還是繼續修復?
若無法確認失敗的套件、有多個套件卡住、無法存取主控台,或伺服器需儘速恢復運作,請還原快照。僅在確認故障原因且只需單一指令即可修復時,才選擇繼續修復。還原前請務必將 /var/log/dist-upgrade/ 複製到伺服器外部,否則第二次嘗試仍會因相同原因失敗。