ISOイメージのみでFreeBSDアップグレード

FreeBSDのSTABLEを追っかけたくても、PCが古くてbuildworldがつらい。
となると、1ヶ月に一度作られるsnapshotからインストールすることになるが、いちいちCDに焼いて、そこからブートするのも面倒。

ということで、ISOイメージを使って、FreeBSDを7.0-BETA4からRC1にアップグレードしたときのメモ。

無保証。
謙遜で無保証と言ってる訳でなく、本当に無保証。
これで合ってるのかどうか分からない。一応7.0current200709→current200710→BETA1→BETA2→RC1と歩いて来たけれども、マイナーバージョンアップグレードしかしてないから問題が出ていないだけの可能性も。


◎全体のおおまかな流れ
 1.ISOイメージのダウンロード
 2.ISOイメージからファイルの取り出し。
 3.schgフラグを外す
 4.カーネルを展開
 5.リブート
 6./etcを除いたベースシステムを展開
 7.mergemaster
 8.リブート

以下、実際の作業


◎何はともあれ、バックアップ
/etc配下のファイルと、カーネルをバックアップ

# cp -pR /etc /etc.080111
# cp -pR /boot/kernel /boot/kernel.080111

◎ISOイメージのマウント

# mdconfig -a -t vnode -f 7.0-RC1-i386-disc1.iso -u 10
# /sbin/mount_cd9660 /dev/md10 /mnt

◎必要なファイルのコピー
カーネルユーザランド(て表現で合ってるのか?要するにworld部分)と、/etc配下ファイルのソースなど、必要なファイルをすべて抜き出しておく。これは、後でISOイメージをマウント出来るかどうか分からないため。

配布ファイルは、フロッピーディスクでインストールしていた時代の名残で1.44Mごとに分割されているため、それを連結しどこかに置いておく。
どこかとは言っても、後々、新しいカーネルでもマウントできるようなファイルシステムに置くこと。
以下の例では、マニュアルページなどもついでにコピーしている。インストールが終わったら、改めてISOイメージをマウントし、install.shでコピーする手もあるが、そこは好き好きで。

# mkdir /usr/archive
# cat /mnt/7.0-RC1/base/base.?? > /usr/archive/base.tgz
# cat /mnt/7.0-RC1/kernels/generic.?? > /usr/archive/generic.tgz

# cat /mnt/7.0-RC1/manpages/manpages.?? > /usr/archive/manpages.tgz

srcは下記のようにして/usr/src配下に展開しておく。

# cd /mnt/7.0-RC1/src
# sh install.sh all
Extracting sources into /usr/src...
  Extracting source component: <略>
Done extracting sources.


◎schgフラグを外す
システム上、重要なファイルはschgフラグがセットされ、rootであっても上書きできないようになっているので、そのフラグを外す。
なお、システムのセキュリティレベルが1以上に設定されていると、フラグは変更できないので念のため。
確認方法。詳しくはman security。

# sysctl kern.securelevel
kern.securelevel: -1

まずschgフラグがセットされているファイルを探す。こんな風にしてみた。

# find / -flags schg -exec ls -lo {} \; |cut -d ' ' -f 13 > /tmp/flaglist

/tmp/flaglistの中身はこんな感じ。

/usr/bin/chpass
/usr/bin/chfn
/usr/bin/chsh
/usr/bin/login
/usr/bin/opieinfo
/usr/bin/opiepasswd
/usr/bin/passwd
/usr/bin/rlogin
/usr/bin/rsh
/usr/bin/su
/usr/bin/crontab
/usr/lib/libkse.so.3
/usr/lib/librt.so.1
/usr/sbin/sliplogin
/bin/rcp
/lib/libc.so.7
/lib/libcrypt.so.4
/lib/libthr.so.3
/libexec/ld-elf.so.1
/sbin/init

中身を確認して問題なければフラグを外す。xargs使うほどの量でもないけれども。

# xargs chflags noschg < /tmp/flaglist

ていうか、/bin /usr/bin /sbin /usr/sbin/ /lib /usr/lib /libexec /usr/libexecあたりの配下ファイル全部に対してchflags noschgしちゃってもいい、というか早い。


カーネルの展開
先にコピーしておいたgeneric.tgzを展開。

# cd /usr/archive
# tar -Upxvzf /usr/archive/generic.tgz


念には念を入れてオリジナルのkernelをmvし、上で展開しておいた新kernelを/boot配下へ移動

# mv /boot/kernel /boot/kernel.orig
# mv /usr/archive/GENERIC /boot/kernel


◎リブート
祈りつつリブートし、カーネルが正しく入れ替わっていることを確認。

# uname -a
FreeBSD xxxx 7.0-RC1 FreeBSD 7.0-RC1 #0: Mon Dec 24 12:18:24 UTC 2007     root@logan.cse.buffalo.edu:/usr/obj/usr/src/sys/GENERIC  i386

RC1になってる。
そもそもブートしなかったら/boot/kernel.orig/kernelから起動して、アップグレードは諦める。


◎worldの展開
いちばん緊張するところ。
base.tgzを展開するが、気をつけないと/etcが上書きされて死亡するので、しっかり/etcをexcludeすること。

# /rescue/tar -Upxvzf /usr/archive/base.tgz -C / --exclude ./etc

この後、mergemasterで新しい/etc配下ファイルとマージする。

リブートして完了。
あとは必要であればportsなど適当にアップグレード。

以上。