Pacman のアップグレードを中断したら Arch Linux が起動しなくなった&復旧まで

作成

事件概要

最近, 外付け HDD を取り外す際に電源を切る (udiskctrl poweroff) とPCがフリーズするという問題がありました. 外付け HDD を使う頻度が低かったので, そのうち直そうなんて思っていたところ, パッケージのアップグレード (pacman -Syu) をしている最中にやらかしました.

以下が再起動をかけて表れたメッセージです. 最後の行にシェルが表示されていますが, いかなる入力も受け付けませんでした.

:: running early hook [udev]
Warning: /lib/modules/4.16.9-1-ARCH/modules.devname not found - ignoring
starting version 238
:: running hook [udev]
:: Triggering uevents...
:: running hook [resume]
:: performing fsck on '/dev/nvme0n1p5'
/dev/nvme0n1p5: clean, 613743/11419648 files, 43211680/45666641 blocks
:: mounting '/dev/nvme0n1p5' on real root
mount /new_root: unknown filesystem type 'ext4'
You are now being dropped into an emergency shell.
sh: can't access tty: job control turned off
[rootfs ]# _

結局は事なきを得たのですが, そのときやったことを記憶と log を頼りに記録しておこうと思います.

解決

アップグレード中だったパッケージの中に linux があったので, それが中断されたことによる問題だろうと推測しました.

USB メモリから chroot

前述の通り起動しませんので USB メモリに用意した Arch Linux からディスクをマウントして chroot します.

# mount /mnt /dev/nvme0n1p5
# mount /mnt/boot /dev/nvme0n1p1
# arch-chroot /mnt

ネットワークの設定

# ip link set wlp4s0 up
# wpa_supplicant -B -i wlp4s0 -c <(wpa_passphrase "ssid" "psk")

原因究明

Pacman のログ (/var/log/pacman.log) を見ると

...
[2018-05-21 02:18] [ALPM] transaction started
...
[2018-05-21 02:18] [ALPM] upgraded linux (4.16.8-1 -> 4.16.9-1)
...
[2018-05-21 02:18] [ALPM] upgraded pandoc (2.2.1-4 -> 2.2.1-5)
EOF

通常であれば, パッケージのアップグレードを終えたあと post transaction hook が実行され, そのなかで mkinitcpio が実行されるはずでした. しかし, すべてのパッケージがアップグレードされる前に中断されてしまったせいで, それが行われませんでした.

いきなり mkinitcpio を実行してもエラー (「ERROR: module not found: `...'」) がでたので, pacman -Syu をやり直すことにしました. /var/lib/pacman/db.lck を削除して実行してみると, 既にアップグレード済みということになっていました.

# pacman -Syu
LockError(/var/lib/pacman/db.lck): failed to lock database [[Errno 17] File exists: '/var/lib/pacman/db.lck']
# rm /var/lib/pacman/db.lck
# pacman -Syu
:: Synchronizing package databases...
...
:: Starting full system upgrade...
 there is nothing to do

そこで linux を再インストール.

# pacman -Syu linux

すると ldconfig による警告が出たのでした.

ldconfig: File ... is empty, not checked.

このときの post transaction hook で実行された mkinitcpio はうまくいったようですが, 上記エラーが怖い.

全パッケージの再インストールを試みますが, エラー.

pacman -Qnq | pacman -S -

エラー内容は次のようなもの.

error: failed to commit transaction (conflicting files)
...: ... exists in filesystem
...
Errors occurred, no packages were upgraded.

依存関係のトラブルらしいです. --force フラグ付きで実行すればよいみたい. 恐らくアップグレードが中断されたパッケージ関係なので, それらを再インストールすればよかったはずですが, このときは頭が回っていなかったので,

# pacman -Qnq | sed '1,800d' | head -100 | pacman -S -

みたいにして, エラーが起きたパッケージを探して --force 付き再インストールするなんてことをやりました (最後のほうは面倒になってまとめて --force しちゃった気もする).

これで

# mkinitcpio -p linux

も無事に実行できました. 再起動してみれば, 無事見慣れた画面が表れましたとさ. いまのところは問題は起きていません. めでたし.