Ubuntu 24.04から26.04へのupgrade失敗を復旧する方法
24.04から26.04へのupgradeが停止したときの復旧手順です。screenセッションの再接続、dpkgの修復、26.04へ変わったsourcesの修正、snapshotへ戻す判断を解説します。
Ubuntu upgrade が途中で失敗した場合: まず症状を確認する
24.04 から 26.04 への Ubuntu release upgrade に失敗すると、サーバーは4つの状態のいずれかになります。状態ごとに対処方法が異なります。upgrader が、接続を失った screen セッション内でまだ実行中の場合があります。dpkg が停止され、パッケージの設定が途中で止まっている可能性もあります。この場合、apt はすべてのコマンドを拒否します。apt の sources が 26.04 を示している一方で、インストール済みパッケージはまだ 24.04 のままの場合もあります。また、サーバー自体が起動しない場合もあります。何かを入力する前に、4つの状態のどれに該当するかを確認してください。ある状態への対処が、別の状態を悪化させることがあるためです。
4つすべてに共通するルールが1つあります。dpkg の状態を確認するまで、再起動しないでください。パッケージの置き換え中に再起動すると、修復可能な dpkg の中断が、このガイドの後半にある起動不能の状態へ変わることがあります。また、最初の apt または dpkg プロセスがまだ実行中の可能性がある場合は、2つ目の apt または dpkg プロセスを開始しないでください。パッケージデータベースに対する2つの書き込み処理が、データベースの破損を引き起こします。
このガイドでは、24.04 から 26.04 への upgrade ガイドに従い、開始前に snapshot を取得していることを前提とします。取得していない場合は、その点を踏まえて boot セクションを読んでください。最悪のケースでは、snapshot が復旧手段になります。
Is the upgrade still running?
Many upgrades reported as failed are still running. The SSH session dropped, the terminal went blank, and the upgrader carried on without you.
do-release-upgrade is built for this. When it runs with its text interface, which is what a server gets, it wraps itself in a GNU screen session, so the upgrade survives the loss of the terminal that started it. Separately, when it detects that it was started from an SSH session, it offers to start a second sshd on another port (1022 by default) so you can still log in if the main SSH daemon breaks during the package swap. Both facts matter now.
Reconnect over SSH and look for the screen session. The upgrader ran under sudo, so its screen session belongs to root, and a plain screen -ls as your own user will not list it.
sudo screen -lsscreen -ls marks each session as attached or detached. If one is listed, reattach to it. If it is still marked attached because the dead SSH connection never released it, -d detaches that stale attachment first.
sudo screen -d -rIf more than one session is listed, put the session name from screen -ls after -r. Running sudo do-release-upgrade again also works: the upgrader checks for its own existing screen session and reattaches instead of starting a new run. Either way you land back in the running upgrade, which is usually waiting at a prompt about a changed config file or a service restart. Answer it and let it finish.
If you started the upgrade inside tmux, as the upgrade guide recommends, reattach tmux first with tmux attach. The screen session is running inside that tmux pane, so you see the upgrade directly. If the pane holds only a shell prompt, the upgrader is no longer running there, and sudo screen -ls is the next check.
If the main SSH port refuses the connection, try the fallback port: ssh -p 1022 user@host. That daemon exists only for the life of the upgrade, so if you cannot get in on either port, use your provider's console instead. From the console, sudo ss -ltnp shows which ports an sshd process is listening on, and sudo ufw status tells you whether the firewall let the fallback port through.
When no screen session exists and nothing is waiting on the console, the upgrade really did stop. Confirm nothing is still working on the package database before you touch it:
ps -eo pid,etime,cmd | grep -iE '[u]pgrade|[d]pkg|[a]pt'An empty result means dpkg is idle and you can move on to repairing it. A dpkg or apt process with a long elapsed time and no screen session to reattach is hung. Give it a few minutes, check the console for a debconf question nobody answered, and only then kill it. Never delete the lock files under /var/lib/dpkg/ or /var/lib/apt/lists/ while a process holds them. The lock is the only thing stopping two writers from corrupting the package database.
dpkg が中断され、apt が実行を拒否する
パッケージの展開後、設定スクリプトの実行前に dpkg が強制終了されると、未完了の状態が /var/lib/dpkg/status に記録されます。その後の apt コマンドはすべてこの状態を読み取り、処理を停止します。未完了の処理が残るデータベースを前提に、apt は処理を続行できないためです。apt が拒否時にどのようなメッセージを表示しても、最初に行うことは同じです。
sudo dpkg --configure -aこれにより、展開済みで未設定のパッケージについて設定処理が完了します。依存関係の順序に従って maintainer script を実行します。アップグレードが途中で止まったシステムでは時間がかかることがあるため、処理が戻るまでそのまま待ちます。パッケージで停止した場合は、パッケージ名と失敗したスクリプトが表示されます。その名前を控えてください。アップグレードを停止させたパッケージであり、次のセクションでそのエラーの読み方を説明します。
次に、割り込みによって未解決になった依存関係を apt に修復させます。一部のパッケージは更新された一方で、それらが依存するパッケージは更新されていない場合があるためです。
sudo apt --fix-broken install続いて、アップグレード処理が途中まで進めていたアップグレードを完了します。
sudo apt update
sudo apt full-upgradeupgrade ではなく full-upgrade を使用してください。リリースアップグレードではパッケージが削除されますが、通常の upgrade は何も削除しないためです。確認する前に、apt が表示する概要を読みます。削除対象が少数であれば通常です。ただし、ubuntu-server、systemd、openssh-server、またはカーネルパッケージを削除する一覧が表示された場合は通常ではありません。いったん no と答え、続行する前に apt がそれらを削除しようとする理由を確認してください。
ほかの操作を行う前に、結果を確認します。
sudo dpkg --audit
sudo apt-get checkdpkg --audit は、壊れた状態のまま残っているすべてのパッケージを一覧表示します。apt-get check は未解決の依存関係を報告します。どちらも何も表示しないことが正常です。表示された場合は、sudo apt autoremove を実行して、依存するパッケージがなくなった 24.04 のパッケージを削除します。次に 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 が出力した端末の内容、つまり画面を流れていったテキストと同じものが記録されています。末尾より前に最後に登場するパッケージが、アップグレード停止時に処理されていたパッケージです。maintainer script が失敗した場合は、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 と照合してください。/var/log/dpkg.log には、dpkg が行ったすべての状態変更がタイムスタンプ付きで記録されています。tail -n 30 /var/log/dpkg.log は、dpkg が最後に処理したパッケージと、そのパッケージに対して行っていた処理を示します。これは別の情報源による同じ確認結果です。
この段階でサーバー上に発生する失敗の多くは、いくつかの原因に分類できます。パッケージが postinst で再起動するサービスが、カスタマイズした設定ファイルのために起動に失敗する場合があります。そのサービスについて systemctl status と journalctl -xeu を確認すると、受け付けられない行が分かります。ディスク容量が不足することもあります。特に、古いカーネルがある /boot や、apt のパッケージキャッシュがある /var で発生しやすく、df -h / /boot /var で確認できます。apt がほかの処理で停止していても、sudo apt clean でキャッシュを空にできます。du では使用量が合わないのにディスクが満杯と報告される場合 には、別の原因があります。アップグレードツールが無効化したサードパーティーリポジトリのパッケージが、26.04 では提供されなくなったライブラリに依存している場合もあります。hold されたパッケージ(apt-mark showhold)が、依存関係にあるパッケージの更新を妨げることもあります。原因を修正してから、sudo dpkg --configure -a を再度実行します。停止した位置から処理が再開されます。
何を行っても 1 つのパッケージの設定に失敗し、重要なパッケージがそれに依存していない場合は、そのパッケージを削除し、アップグレード完了後に再インストールします。
sudo dpkg --remove --force-remove-reinstreq package-name
sudo dpkg --configure -aこの方法は、対象パッケージを特定でき、削除理由を説明できる場合にだけ使用してください。ライブラリや ubuntu-server の依存関係チェーンに含まれるものには使用しないでください。強制削除では、ほかに何が壊れるかを知らせるチェックが省略されるためです。
ソースは切り替わったが、パッケージは切り替わっていない
アップグレーダーは、パッケージをダウンロードする前の早い段階で APT のソースを書き換えます。その後で処理が中断されると、ソースは 26.04 を示す一方、インストール済みパッケージは複数のリリースが混在します。この混在によってツールが正しく動作せず、do-release-upgrade が新しいリリースはないと主張する原因になります。
現在どのリリースを使用しているかを示す 2 つの場所を比較します。/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重要なのは 3 つの組み合わせです。ソースが 24.04(コードネーム noble)を示し、os-release も 24.04 を示している場合、アップグレードはチェックを通過していません。main.log を読んで停止した理由を確認してから、sudo do-release-upgrade を再度実行できます。ソースが 26.04 のコードネームを示し、os-release が 24.04 を示している場合、パッケージの入れ替えが開始された後に中断されています。前のセクションで説明した dpkg の修復を、apt full-upgrade で終える方法が完了手順です。ソースが 26.04 を示し、os-release も 26.04 を示している場合、base-files は処理を完了したパッケージの 1 つです。システムの大部分がまだ移行されていなくても、システムは 26.04 と認識しています。
最後の組み合わせが問題になります。do-release-upgrade は、os-release と同じ情報から現在のリリースを判定します。そこですでに 26.04 と示されていると、ツールは 26.04 より新しいリリースを探します。該当するものがないため、新しいリリースはないと報告します。ツールは os-release について質問し、os-release は誤った情報を返しています。アップグレーダーの実行を続けず、APT で完了させます。まず sudo apt update を実行し、次に sudo apt full-upgrade を実行します。sudo apt full-upgrade は 24.04 のバージョンのまま残っているすべてのパッケージをアップグレードします。その後、sudo apt autoremove を実行します。os-release がまだ 24.04 を示している場合は、do-release-upgrade が新しいリリースはないと報告するその他の理由も確認してください。LTS のプロンプトが最初のポイントリリースを待っている場合などがあります。
アップグレーダーは /etc/apt/sources.list.d/ 以下にあるサードパーティーソースも無効にします。また、変更した各ファイルのバックアップを、元の名前にサフィックスを追加して保存します。ls -la /etc/apt/sources.list.d/ と diff を実行し、各オリジナルファイルとバックアップを比較すると、アップグレーダーが行った変更を正確に確認できます。Ubuntu パッケージの整合性が戻るまで、サードパーティーエントリは無効にしておきます。その後、各ベンダーが 26.04 用のパッケージを公開していることを確認してから、1 つずつ再有効化します。apt update がソースの設定が重複していると報告する場合、古い sources.list エントリと新しい ubuntu.sources エントリが同じスイートを記述しています。deb822 の重複ソースエラーで、どちらを削除すべきか確認できます。
アップグレード後にサーバーが起動しない
再起動すると、未完了のアップグレードの影響が表面化します。VPS で考えられる主な原因は、initramfs なしで kernel がインストールされていること、GRUB 設定が再生成されていないこと、起動時に依存する unit のパッケージが未設定のまま残っていること、または dpkg の書き込み中にディスク容量が枯渇したことです。
まず、ほかの操作をする前にプロバイダーのコンソールを開きます。コンソールには、GRUB メニュー、kernel panic、回答待ちのファイルシステムチェック、root パスワードを求める systemd emergency shell のどこで起動が停止したかが表示されます。この確認だけで、次に行うべき手順が決まります。
GRUB が表示されたら、advanced options サブメニューから以前の 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 環境で 1 時間かけて作業する前に、snapshot からの復元と比較してください。開始前に snapshot を取得していれば、ほとんどのプロバイダーでは数分で復元できます。その後、アップグレードを再実行します。VPS では通常 1 時間もかからず、今回は事前に修正すべきパッケージも分かっています。次のいずれかに該当する場合は、復元のほうが速い方法です。コンソールまたは rescue image を利用できない、アップグレードを停止させたパッケージを特定できない、複数のパッケージが停止している、または利用者が待っているサービスをそのサーバーで実行している場合です。手作業で修正するほうが速いのは、壊れた箇所が 1 つに特定でき、修正が単一のコマンドで済む場合だけです。
復元する前に、/var/log/dist-upgrade/ をサーバー外へコピーします。そこへ入る唯一の方法が rescue image なら、その環境からコピーします。復元するとこれらのログが消えるため、最初の失敗理由を確認しなければ、2 回目もまったく同じように失敗します。snapshot で復元できるものとできないものは、snapshot に依存する前に読む価値があります。snapshot はディスク全体を取得時点まで戻すため、取得後に書き込まれたデータも失われます。アップグレード中であれば問題ありませんが、1 週間後では問題になります。
代わりにシステムを再構築すべき3つの兆候
保存する価値のないアップグレードもあります。スナップショットを復元して再実行する方法は簡単ですが、障害の原因がシステム自体の状態にある場合、2回目も失敗します。その場合の適切な対処は、26.04 の新しいイメージを用意し、バックアップからデータを復元することです。次の3つの兆候があれば、再構築すべき状態です。
1つ目は、dpkg 自身のデータベースが破損している場合です。dpkg --audit または apt-get check が /var/lib/dpkg/status を読み取ること自体に失敗し、その中の破損パッケージを報告することもない場合、インストール済みのパッケージを記録したデータが失われています。Ubuntu は /var/backups/(ls -la /var/backups/dpkg.status*)に日次コピーを保存しており、最も新しい正常なコピーに置き換えると復旧できることがあります。しかし、そのコピーの内容が実際にディスク上にある状態と一致しなくなった時点で、推測に頼ることになります。その後の apt の実行もすべて、その推測を前提に進みます。
2つ目は、システムの修復に必要なツール自体が壊れている場合です。共有ライブラリが削除された、または中途半端に置き換えられたために apt や dpkg が起動しない場合、あるいは自身のパッケージが未設定の状態にあるため systemd が unit を起動できない場合、パッケージマネージャーを修復できる稼働中のパッケージマネージャーが残っていません。ldd /usr/bin/apt では、apt のライブラリがすべて存在するかどうかを確認できます。rescue イメージの chroot から復旧できる場合もありますが、通常は再構築より長い時間がかかります。
3つ目は、破損パッケージの一覧が減少しない場合です。dpkg --configure -a と apt --fix-broken install を1時間以上繰り返し実行しても、最後の問題が解消されず、実行するたびに新しいパッケージが見つかる場合、アップグレード前から存在した問題がアップグレード後に引き継がれています。たとえば、/usr 配下のファイルを手動で編集していた、パッケージを pin または hold していた、サードパーティーのリポジトリがコアライブラリを置き換えていた、以前のアップグレードが完了していなかった、といった状態です。新しいイメージにはこれらの問題がなく、データを復元するほうが原因を探すより短時間で済みます。
再構築が簡単に済むのは、データがそのサーバー以外の場所にも存在する場合だけです。これがスナップショットとバックアップの違いであり、アップグレードガイドが両方を求める理由です。
FAQ
do-release-upgrade が中断された後、もう一度実行するだけでよいですか?
はい。それが最初に行うべき方法です。アップグレーダーがまだ screen セッション内で動作している場合は、再度実行するとそのセッションに再接続します。動作していない場合は、最初に sudo dpkg --configure -a と sudo apt --fix-broken install を実行してから、アップグレーダーを再度起動します。現在の状態を読み直し、処理を続行します。/etc/os-release がすでに 26.04 を示している場合だけは、この方法では解決できません。この場合、アップグレードが完了したと判断されるため、sudo apt full-upgrade で仕上げます。
アップグレードに失敗した後、do-release-upgrade が新しいリリースはないと表示するのはなぜですか?
base-files は /etc/os-release を書き込むパッケージであり、中断前にアップグレードされたパッケージの 1 つだからです。ツールは現在そのファイルを読み取り、26.04 を使用中だと判断するため、提示できる新しいリリースがないと判断します。grep VERSION_ID /etc/os-release と grep Suites /etc/apt/sources.list.d/ubuntu.sources を比較し、その後 sudo apt update && sudo apt full-upgrade で仕上げます。
アップグレードが途中の Ubuntu server を再起動しても安全ですか?
sudo dpkg --audit が何も返さない状態になるまでは、安全ではありません。kernel が展開済みで未設定の状態、または GRUB が再生成されていない状態で再起動すると、10 分で修復できたはずのアップグレードが rescue image を使う作業になることが最も多くあります。dpkg の修復と apt full-upgrade を完了し、update-initramfs -u -k all と update-grub を実行してから、再起動してください。
アップグレードを停止させたパッケージを確認するにはどうすればよいですか?
dpkg の最終出力が記録されている /var/log/dist-upgrade/apt-term.log の末尾を確認します。ログが終わる直前に表示された最後のパッケージが、実行中だったパッケージです。maintainer script が失敗した場合は、そのエラーが dpkg のエラー表示の直前に出力されます。tail -n 30 /var/log/dpkg.log でも別の情報源から確認できます。main.log の末尾が Python traceback になっている場合は、アップグレーダー自体がクラッシュしており、パッケージには問題がありません。
snapshot を復元すべきですか、それとも修復を続けるべきですか?
失敗したパッケージを特定できない場合、複数のパッケージが停止している場合、コンソールにアクセスできない場合、または server を早急に復旧する必要がある場合は、復元します。問題の原因を 1 つに絞り込めており、修正が 1 つのコマンドで済む場合だけ、修復を続けます。復元する前に /var/log/dist-upgrade/ を server の外へコピーしてください。そうしないと、2 回目の試行でも同じ理由で失敗します。