FreeBSD の更新

以下の文章は、 4.8-RELEASE が出る前に書いたため、 RELENG_4_7 への更新を例に挙げているが、 4.8-RELEASE が出たので、今後は RELENG_4_8 に更新することのほうが多いであろう。 RELENG_4_7 でも RELENG_4_8 でも standard-supfile に指定するタグを変えればいいだけで、何も手順に違いはない。


RELENG_4_6 の FreeBSD を RELENG_4_7 の最新に上げる方法について書いた、自分のためのメモである。

FreeBSD の更新のとき、ハンドブックの中の makeworld.html は必読。普通に FreeBSD をインストールすると、英語版が /usr/share/doc/handbook/makeworld.html に入っているので、それでもよい。でも、日本語版でも英語版でも、変なことも書いてあるので鵜呑みにしちゃだめ。とくに、ハンドブックに書いてある手順だとシングルユーザモードに落ちるのが意味もなく早い。

ぼくの従っている手順を書いておく。だいたい上の makeworld.html に書いてあるままだが、少し修正したり補足したりしてある。

注意: 間違っていそうだったら致命傷を負う前に確認して、間違っていたら教えてください。

cvsup はデフォルトでは入っていないような気がするが、 net/cvsup-without-gui パッケージ(または net/cvsup パッケージ)を入れておけばよい。古い FreeBSD を使っていてパッケージが見つからない場合は、 cvsup port も使えない可能性が高いので(古い cvsup は互換性がないので使えない)、 cvsup の最新版を取ってきて自分で make して使うこと。 make M3FLAGS="-DSTATIC -DNOGUI" で GUI なし版ができる。

注意

……というか、ミスの記録。

1個所で build{world,kernel} して複数で install{world,kernel} する場合の注意

  • build* したときと install* のときで /etc/make.conf の内容が違うとトラブルが起きるので、必ず揃えておく。特に、 build* のときに NOPROFILE= yes があったのに install* のときに消えていると、 installworld で失敗する。
  • 4.3-RELEASE 以前の /usr/bin/install は、デフォルトでファイルをコピーではなく移動するので、 install{world,kernel} が終わると /usr/obj の下が消えているという悲しい状態になる。やばそうだったら man install などして、 -c の項の説明で確認する。 /usr/bin/install が古い場合は、 /etc/make.conf に INSTALL= install -c と書いておけばよい。

緊張感を高める

1. root になる

具体的には、

su -
umask 022

する。べつに X の kterm の中でも何でもよい。

su でもいいけど、環境変数に変なのが設定してあると苦労するので、 su - が吉。

umask は別に何でもいいと思うが、念のため無難な 022 にしておく。

2. ログファイルなどを保存するディレクトリを掘る

具体的には、

mkdir -p /var/update/log/std-20021015

とか。 /tmp の下はいつ消えるかわかったものではないので、 /tmp の下に掘ってはいけない。

3. /etc をバックアップする

もちろんもっといろいろバックアップしてもいい。注意としては、 /etc のバックアップを root 以外のユーザが読めないようにすること。具体的には、

cd /var/update/log/std-20021015
mkdir backup
touch backup/etc.tar.gz
chmod 0600 backup/etc.tar.gz
( cd / && tar cvzf - etc ) > backup/etc.tar.gz

かな。

ソースファイルなどの準備

4. supfile を用意する

/usr/share/examples/cvsup/standard-supfile を /var/update/ にでもコピーして、 RELENG_4_6 と書いてある場所を RELENG_4_7 に直す。 CHANGE_THIS.FreeBSD.org も cvsup3.jp.FreeBSD.org に直す(近いところを選ぶべき。 cvsup3.jp.FreeBSD.org は東大内にある)。

4.7-RELEASE の standard-supfile には間違いがあって、 RELENG_4_7 と書くべき場所に RELENG_4 と書いてある。これだと 4-STABLE (次の 4.x-RELEASE に向けての開発バージョン)を取ってくることになってしまう。必ず自分の取ってきたいバージョンになっていることを確認すること。

5. ソースファイルを入手する

具体的には、

cd /var/update/log/std-20021015
(date && cvsup -g -L 2 ../../standard-supfile; date) |& tee cvsup.log

かな。

これで、 /usr/src の下が完全に新しくなった。まだ実際に使う部分は何も新しくなってない。

6. /usr/src/UPDATING を読む

英語を楽しむ :)

4.6 から 4.7 だと大したことは書いてないけど、 4.3 から 4.6 に上げたときは結構いろいろ「buildworld 前にこれをしろ」「あれ確認しろ」といろいろ書いてあって読みごたえがあった、というか消耗した (x_x)

部分的な日本語訳を用意しました。眉に唾を付けて読んでください。

7. /etc/make.conf を書く

普通は

CFLAGS= -O -pipe
NOPROFILE= true

の2行。詳しくは /etc/defaults/make.conf を見る。

もちろん OS の更新とは関係ないことがいろいろ書いてあるかもしれないので、そういう行はいじらない。

kernel と world のビルドとインストール

8. mergemaster -p する

具体的には、

env PAGER=/usr/bin/less mergemaster -p

かな。 PAGER を設定し忘れると more になって残念な思いになる(まあ FreeBSD の more は偽物なのでバックスクロールできるけど)。

mergemaster(8) は、 /usr/src/etc の内容からインストールするべき /etc の内容を仮に /var/tmp/temproot/etc に作って、現在の /etc と比較して違うファイルをリストアップしてくれるツール。中身が違うファイルそれぞれについて、「i」を押すと新しいファイルを上書きし、「d」を押すと新しいファイルを削除し(古いままが残る)、何も入れずに Enter を叩くと両方残る。

mergemaster の -p オプションは、ビルドに必要な最小限のファイルだけをチェックする。たぶん /etc/passwd と /etc/group だと思う。 4.6 から 4.7 への更新のときは何も変更しなくていいはずだけど、 $FreeBSD: ……$ の行だけは新しいのに合わせて書き換えておくと、今後のアップデートが少しだけ楽になる。なので d することはあまりない。

すべてを i や d した場合はともかく、そうでなかったら、最後の「/var/tmp/temproot を消すか?」という問いに「消す」と答えてはいけない。消すと答えると、「残しておきたい」と指定したファイルまで一緒に消える。まあ消えるのは /var/tmp/temproot だけなので、間違って消してしまったらもう一度 mergemaster -p すればいいのだが。

9. make buildworld する

具体的には、

cd /var/update/log/std-20021015
( cd /usr/src && date && make buildworld; date ) |& tee buildworld.log

する。時間掛かる :)

10. make buildkernel する

具体的には、カーネル設定ファイルが /usr/src/sys/i386/conf/MYHOST なら、

cd /var/update/log/std-20021015
( cd /usr/src && date && make buildkernel KERNCONF=MYHOST; date ) |& tee buildkernel.log

する。 KERNCONF=MYHOST の部分を省略すると、 KERNCONF=GENERIC と同じ意味になる。自分でカーネル設定ファイルを書いていないなら、これで OK。

11. シングルユーザモードに落ちる

具体的には、

shutdown now

する。 X を使っていた場合はここで X サーバが終了してコンソールに戻る。シェルを聞いてくるので、そのまま Enter で進む(/bin/sh を使うことになる)。ほかのシェルを使ってもいいのかもしれないが、やったことない。

12. make installkernel する

具体的には、

cd /var/update/log/std-20021015
( cd /usr/src && date && make installkernel KERNCONF=MYHOST; date ) 2>&1 | tee installkernel.log

する(csh でないのでパイプの方法が違うことに注意)。1分もかからずに終わる。

13. シングルユーザモードで再起動する

具体的には、

shutdown -r now

として、 Load kernel in 10 seconds... の待ちに入ったらスペースバーでも叩いて止めて、 boot -s と入れる。またシェルを聞いてくるので Enter を押す。

万一、ここで立ち上がらなかったら、再起動して、初めの - と出て待っているところでスペースで止めて、 /kernel.old を指定すると、とりあえず installkernel 前の古いカーネルで起動する。そこでシングルユーザモードで起動して mv /kernel.old /kernel とすればとりあえず元には戻る。更新できてないけど、それは落ち着いて考える :)

14. boot -s したときのおまじないをとなえる

具体的には、

fsck -p
adjkerntz -i
mount -u /
mount -a -t ufs
swapon -a

する。

これらは普通に(マルチユーザモードで)起動した場合には自動的にやってくれるが、シングルユーザモードではやってくれないので、自分でやる必要がある。それぞれの説明は man を見るがよろし。 fsck(8), adjkerntz(8), mount(8), swapon(8)

また、日本語キーボードを使っているなら、上述のコマンドの後で kbdcontrol -l jp.106x などを実行するといいかもしれない。なお、 jp.106x は Shift の上が Ctrl の場合。 Shift の下が Ctrl の場合は jp.106x の代わりに jp.106 とする。

以前このページでは adjkerntz -imountswapon の後に書いていたが、ファイルシステムを読み書きモードでマウントすると最終マウント時刻として現在の時刻がディスクに書き込まれるので、この時点では時刻が正しいほうがよい、と思う。まだきちっと理解していない。

15. make installworld する

具体的には、

cd /var/update/log/std-20021015
( cd /usr/src && date && make installworld; date ) 2>&1 | tee installworld.log

する。

ここでハマると、かなり大変なことになる。というか、ここでハマったらぼくはどうしていいかわからない。なのでハマらないようにする(謎)

installworld が終わっても、再起動してはいけない。

ここまでで半分

一息つく。 (^_^;)

/etc の更新

16. mergemaster する

具体的には、

PAGER=/usr/bin/less mergemaster

とか。これはかなり気合いが必要。

とくに、普通初めて更新するときは、 /etc に何があるかなんて知らないので、 mergemaster を実行して初めて見るファイルなんてのもざら。その状態でどうやって更新するか否か決めろというの(そんなのぼくだけですか、そうですか)。

なので、指針としては、

  • 昔のバージョンをインストールした後で自分でいじったファイル(diff の最初にファイルの日付が出るのでそれを見るとわかるかも)は後回しにして、それ以外を i で更新する。
  • 自分でいじったファイルについては、頑張って見比べる。 m など選ぶと操作がわからなくて大変なので選ばない。 i でも d でもないファイルは、後回しにして mergemaster 終了後に vi か何かでいじるべし。
  • mergemaster で表示されるのは CVS タグ $FreeBSD: ……$ が変更されたファイルだけなので、出てきたファイルはすべて内容を読んで、変更する必要がなくても $FreeBSD: ……$ だけは新しいのに合わせておくと、次の OS 更新時にひょっとすると(そのファイルが更新されていなければ表示されなくなるので)楽ができるかもしれない。

という感じか。

それと、 /etc/motd の新しいほうにはバージョン番号が入っていないが、これは後で勝手に入るので、気にせず i してよい。

違いがあったすべてのファイル(正確には CVS タグが異なるすべてのファイル)について答え終わると、そのときに変更したファイルによっては、「……する必要がありますが、してあげましょうか」という質問がくるので、意味がわからなかったぼくは yes と答えた :) というか /usr/src/UPDATING とハンドブックはまじめに読みましょう(←もはや説得力ゼロ)。

/stand の更新

17. /stand を更新する

/stand は自動的には更新されないので、更新したい場合は手動で更新する必要があるらしい。具体的には、

cd /usr/src/release/sysinstall
make all install

した後で、 /stand にある sysinstall 以外のファイルを sysinstall へのハードリンクにする、らしい。やったことがないのでよく知らない……。参考: Why is my /stand/ much older than my FreeBSD? [freebsd-questions]

動作確認

18. 再起動して、普通に起動することを確認する

shutdown -r now

で普通に放っておけばよい。せっかちなら起動時に2回か3回 Enter を押すかも。

ここでうまく起動しない場合は、どうするんだろう。シングルユーザモードで起動して、ログファイルとか起動スクリプトとかをチェックするのかな。

19. ログインする

今まで通り普通にログインして、起動時のメッセージの先頭に出るバージョン番号が新しくなっているのを確認して喜ぶ。または、 uname -a して新しいバージョンが出ることを確認して喜ぶ。


東京大学 大学院情報理工学系研究科 コンピュータ科学専攻 今井研究室 伊藤剛志

tsuyoshi at is.s.u-tokyo.ac.jp