さくらの専用サーバに入っている FreeBSD 5.4-RELEASE を 6.3-RELEASE にリモートアップデートしてみた
現在、ジョグノートで借りている さくらインターネット のサーバで、古いものは FreeBSD の 5.x 系が入っています。
先日 7.0 がリリースされて、6.x シリーズも Legacy になったので、そろそろ 5.x 系も 6.x 系にアップグレードすることにしました。
基本的には handbook にある通りに作業をすればよいわけですが、物理的に完全に隔離された場所にサーバがあり、コンソールはおろか、リセットスイッチさえ押せないので、全ての作業をリモートから行う必要があります。
handbook の手順だと、一旦シングルユーザモードでの再起動が必要になりますが、リモートでアップグレードを行う場合には、そうするわけにはいきません。
マシンに接続されているキーボードにアクセスすることができないので、ブートマネージャにシングルユーザモードで起動する旨を伝えることもできないし、仮にさくらの人に何とかしてもらうことにして、シングルユーザモードで起動しても、telnet や ssh で中に入ることはできません。
シングルユーザモードですから、直接 root で作業をするしかないのです。
ということで、途中でシングルユーザモードでの再起動をしないで全ての作業を行う、というのが、今回のアップグレードの要になります。
さて、作業の手順です。
まずは cvsup を用いて最新版のソースを取ってきます。
/usr/share/examples/cvsup/standard-supfile あたりを参考に、次の内容でファイルを用意します。
*default host=cvsup2.jp.FreeBSD.org
*default base=/var/db
*default prefix=/usr
*default release=cvs tag=RELENG_6_3
*default delete use-rel-suffix
src-all
余談ですが、host として指定した cvsup2.jp.FreeBSD.org は、実はYahoo! JAPANのサーバだったりします^^;
Yahoo! JAPAN は FreeBSD のヘビーユーザとしても有名ですね。
; <<>> DiG 9.3.4-P1 <<>> cvsup2.jp.FreeBSD.org
;; global options: printcmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 6497
;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 0
;; QUESTION SECTION:
;cvsup2.jp.FreeBSD.org. IN A
;; ANSWER SECTION:
cvsup2.jp.FreeBSD.org. 3600 IN CNAME mukku.bsd.yahoo.co.jp.
mukku.bsd.yahoo.co.jp. 900 IN A 203.216.196.85
;; Query time: 5 msec
;; SERVER: 210.188.224.10#53(210.188.224.10)
;; WHEN: Tue May 13 19:05:18 2008
;; MSG SIZE rcvd: 90
作成したファイルを引数に指定して cvsup を実行。
% sudo cvsup -L 2 -g ~/releng_6_3-supfile
/usr/src 以下が 6.3-RELEASE の状態になります。
FreeBSD のソースからのアップグレードを解説しているサイトでは、いろんなところで /usr/src/UPDATINGM を熟読するように、と書いてあります。
でも、とてもじゃないけど全部熟読して理解できるほど FreeBSD に精通していないので、さらっと全体を眺めることにしました。
ここからは、作業のログを取っておくことにします。script コマンドを使うと、それ以降に端末に流れる文字をファイルに記録しておくことができます。
% script ~/upgrade.log
カーネルには GENERIC の設定をそのまま使うので、特にパラメータは指定することなく次のように実行します。
% cd /usr/src
% sudo make buildworld
% sudo make buildkernel
% sudo make installkernel
% sudo make installworld
どうやら 6.x からは audit グループが必要なようで、audit グループが無い状態で installworld しようとしたら、次のエラーが出て先に進めませんでした。
ERROR: Required audit group is missing, see /usr/src/UPDATING.
*** Error code 1 [#uea0ff7f]
Stop in /usr/src.
*** Error code 1 [#ca3dda06]
Stop in /usr/src.
他の 6.x 系のサーバの /etc/group を参考にしながら、次のようにしてグループを作成しました。
% sudo pw groupadd audit -g 77
ちなみに、audit のことはちゃんと /usr/src/UPDATING に書いてありました。
本来であれば installkernel の後でシングルユーザモードで起動して、その後に installworld, mergemaster とするそうですが、ここでは一気にやってしまうことにします。
installworld が済んだら mergemaster の実行に移ります。
これを実行することにより /etc 以下を新しいバージョンに対応させます。
基本的には i を押して、新しいファイルをインストールするのですが、/etc/group とか自分で編集した記憶があるファイルは上書きしてしまわないように注意が必要です。
diff 形式で差分が表示されているので、古いファイルを元に新しいファイルの内容を加えたり、新しいファイルに古い設定を加えたりしてマージします。
特に /etc/master.passwd のマージは要注意です。
mergemaster で m によるマージの作業は、癖があってとても使いやすいとは言えないものでした。
それでも、l とか l とか el とか押しながら、何度も途中で最初から編集をやり直しながら、マージしたファイルをインストールしていきます。
mergemaster が完了したら、OS を再起動します。
ここで、もしかして何かの設定がおかしくて ssh で入れないことも考えられるので、telnet でのログインを有効にしておきます。
FreeBSD では telnet は inetd 経由で起動されるので、/etc/inetd.conf を次のように設定しておきます。
% diff -cu inetd.conf.orig inetd.conf
--- inetd.conf.orig 2008-05-14 12:48:16.000000000 +0900
+++ inetd.conf 2008-05-14 13:16:16.000000000 +0900
@@ -12,7 +12,7 @@
#ftp stream tcp6 nowait root /usr/libexec/lukemftpd ftpd -l -r
#ssh stream tcp nowait root /usr/sbin/sshd sshd -i -4
#ssh stream tcp6 nowait root /usr/sbin/sshd sshd -i -6
-#telnet stream tcp nowait root /usr/libexec/telnetd telnetd
+telnet stream tcp nowait root /usr/libexec/telnetd telnetd
#telnet stream tcp6 nowait root /usr/libexec/telnetd telnetd
#shell stream tcp nowait root /usr/libexec/rshd rshd
#shell stream tcp6 nowait root /usr/libexec/rshd rshd
いよいよ再起動です。ちゃんと OS が上がってくるか緊張します。
% sudo /sbin/shutdown -r now
1,2分くらいして、ping が返ってくるようになりました。
無事 ssh でもログインできるようです。
uname -a して OS のバージョンが新しくなっていることを確認します。
FreeBSD localhost 6.3-RELEASE-p2 FreeBSD 6.3-RELEASE-p2 #0: Tue May 13 10:43:20 JST 2008 root@localhost:/usr/obj/usr/src/sys/GENERIC i386
OS のバージョンが上がっていることを確認できたら、再起動前に設定した telnet のポートをすぐに閉じます。
/etc/inetd.conf の該当行をコメントアウトし、
% sudo kill -HUP `sudo cat /var/run/inetd.pid`
のようにして SIGHUP を送れば OK です。
OS のバージョンアップの次は、ports の再コンパイルです。
GENERIC では COMPAT_FREEBSD5 が設定されているので、FreeBSD 5.x 系のバイナリもそのまま動くと思われがちですが、中には動かないものもあるので、インストールされている ports は全て再コンパイルしてインストールすることにします。
まずは ports collection のアップデート。
% sudo cvsup -L 2 -h cvsup2.jp.FreeBSD.org /usr/share/examples/cvsup/ports-supfile
次に現在インストールされているパッケージの整合性のチェック。
% sudo pkgdb -F
もし pkgdb -F で
---> Checking the package registry database
[Updating the pkgdb <format:bdb_btree> in /var/db/pkg ... /var/db/pkg/pkgdb.db: unexpected file type or format -- Invalid argument; rebuild needed] [Rebuilding the pkgdb
<format:bdb_btree> in /var/db/pkg ... /var/db/pkg/pkgdb.db: unexpected file type or format -- Invalid argument: Cannot update the pkgdb!]: Cannot update the pkgdb!]
</format:bdb_btree></format:bdb_btree>
のようなエラーが出た場合には、
% sudo rm /var/db/pkg/pkgdb.db /usr/ports/INDEX*.db
% sudo pkgdb -fu
とすればよさそうです。
一気にアップグレード。
% sudo portupgrade -afr
ports を含め、インストールされている全てのバイナリが新しくなったら、古いバイナリは削除してやります。
% cd /usr/src
% sudo make check-old
% sudo make delete-old
% sudo make delete-old-libs
アップグレートが完了したら、新しい OS のバイナリを作るための作業ディレクトリである /usr/obj も削除すると、/usr の空き容量が増えます。調べてみると、けっこうな容量を使っています。
% du -sh /usr/obj
734M /usr/obj
handbook によると、
# cd /usr/obj
# chflags -R noschg *
# rm -rf *
とあり、schg フラグを落としてから削除するようにとのことだが、実際にどれくらい schg フラグが立っているファイルがあるのかと調べてみると、
% find /usr/obj -flags schg
1つも見つかりませんでした。なので chflags しないで直接削除しても大丈夫そうです。
また、GENERIC をそのまま使ってビルドした場合は、作ったバイナリがそのまま他のマシンでも使えるので、
% cd /usr; sudo tar zcf - obj src | ssh remotehost 'cd /usr; sudo tar zxf -'
のようにして他のマシンにもコピーすれば、コピーした先のマシンでは
% sudo make installkernel
% sudo make installworld
% sudo mergemaster
だけを実行すればよく、時間の節約になります。
以上、完全リモート操作による FreeBSD のメジャーバージョンアップの手順でした。