/usr/以下が全てなくなった時にどうすればいいのか

概要

ある日Ubuntuを何気なく起動したところ*1/usr/以下がほぼ消失していたので何とかして直しましたとさ。

その惨状の発見まで

Ubuntuの起動が遅いと思ってから、/usr/以下がほぼ消失していることに気づくには時間はかからなかった。コンソールでログインしようとしてもシェルが起動するまでの間にとてつもなく大量のエラーを吐いていたからだ。とにかくログインはできたので見てみると/homeは生きていたのでとりあえず安心したものの、/usr/以下には/usr/src/以外何もないという状態だった。

対処方法

Live CDでの起動

こうなってしまってはどうしようも無いのでとりあえずWindowsなどからUbuntuのLive CDをダウンロードする。これをCDに焼きたいところだが面倒なのでSDカードに放り込んでGRUB2から直接起動しよう。以下のコマンドをGRUB2の画面上で入力。

loopback loop (hd0,1)/ubuntu-ja-12.04-desktop-i386.iso
linux (loop)/casper/vmlinuz boot=casper iso-scan/filename=/ubuntu-ja-12.04-desktop-i386.iso noprompt noeject
initrd (loop)/casper/initrd.lz
boot

あっさり立ち上がった。

ファイルの復旧(失敗)

次にextundeleteというソフトウェアで復旧を試みる。うまく行くかは全くわからないが。

sudo apt-get install extundelete
sudo extundelete --restore-directory '/usr/' --output-dir "/media/2fb1e6b8-2a7b-405c-9bcc-d602f7baf9c2/" --after `date -d "2012-09-04T08:18:00" +%s` /dev/sda5
#失敗
sudo extundelete --restore-all --output-dir "/media/2fb1e6b8-2a7b-405c-9bcc-d602f7baf9c2/" /dev/sda5
#失敗

全く何も引っかからなかった。

aptによる復旧

幸い飛んだファイルは/etc/でもなく/home/でもなく、/usr/でありこれはパッケージに含まれるファイルそのままである。つまり、/usr/のファイルはaptを駆使すれば理論上回復できるべきである。以下元のファイルシステムの/を/media/root/にマウントして行なっている。
まず、/usr/以下にファイルをインストールするパッケージを検索した。

~$ dpkg-query --admindir=/media/root/var/lib/dpkg -S "/usr/" | tr ',' ' ' > /tmp/pkglist
~$ vim /tmp/pkglist # 末尾の余計な文字列を削除する

なぜかdpkgはadmindirやinstdirという形で/以外へのインストールができるのに対してaptはそのような器用なことはできないようだ。なのでchrootを試みる。(rbind: http://d.hatena.ne.jp/tmatsuu/20101225/1293262061)

~$ sudo mount --rbind /dev /media/root/dev
~$ sudo mount --rbind /sys /media/root/sys
~$ sudo mount -t proc none /media/root/proc
~$ sudo mount --bind /tmp /media/root/tmp
~$ sudo chroot /media/root/
/# apt-get
bash: apt-get: command not found

oops...というわけで、必要なファイルをコピーしておこうかと思ったが、思ったより多くのファイルが必要なので/usr/以下をごっそりコピーする。
後でエラーが出るとがっかりするのでhaskell-platformやemacsをインストールしてある人はLiveCD側でもインストールしておこう。

sudo cp -Rd /usr/{bin,include,lib,local,sbin,share,games} /media/root/usr/

これでとりあえず動くようになった。
tex関連: tex-commonを先に再インストールする。

/# apt-get install --reinstall `cat /tmp/pkglist` | tee hoge.log
Reading package lists... Done
Building dependency tree       
Reading state information... Done
Package gnome-themes is not available, but is referred to by another package.
This may mean that the package is missing, has been obsoleted, or
is only available from another source

...(略)

E: Package 'gnome-themes' has no installation candidate
E: Package 'gnome-themes-more' has no installation candidate
E: Package 'python2.6' has no installation candidate

ダミーパッケージを含んでいたようだ。怒られたパッケージを削除してもう一度やり直す。しかし、aptは特定のクエリを与えるとSegmentation Faultしてしまうことがわかったのだ。

apt-get install --reinstall libtcltk-ruby1.9.1 debconf libpam-modules-bin libpam-modules gconf-service-backend gconf-service

何も言わずに落ちるからビビるけどたしかに死んでいる。こういうこともあるので、全部まとめてreinstallしようという試みは成功しないことが多い。故に適当に分割して食わせていくしかない。
また、依存関係があるパッケージは依存されている方から再インストールしたほうがいい。なのでエラーが出たらそれを疑って依存されてる方から再インストールしてみよう。こういう泥臭いことをやり続ければうまく行きました!

 --no-download --ignore-missing
#0  0xb75ef744 in pkgCache::DepIterator::IsIgnorable(pkgCache::PkgIterator const&) const () from /usr/lib/i386-linux-gnu/libapt-pkg.so.4.12

最後に

結局「なぜ/usr/が飛んだのか」がわからないと正直怖くて使いたくない。恐る恐る使っています。なんで飛んだんだろうか。

*1:puppy linuxでファイルの復旧をしようとしていたのでこれは嘘です