18.7. “world” の再構築

FreeBSD のどれか特定のバージョン (FreeBSD-STABLE、FreeBSD-CURRENT など) について、ローカルのソースツリーを同期させたら、 そのソースツリーを使ってシステムを再構築できます。

バックアップの作成システムを再構築する前にバックアップを 作成することの重要性は、いくら強調してもし過ぎると言うことはありません。 システム全体の再構築とは (以降に書かれた手順に従っている限り) 難しい作業ではありませんが、 どんなに注意していたとしても、 あなた自身、あるいはソースツリーで作業している他の人達に手違いがあった時には、 システムが起動しなくなってしまう状態になることがあるのです。

まず、バックアップがきちんと作成されていることを確認して、 fixit フロッピーか起動可能な CD を用意してください。 多分、それを使うことはないと思いますが、 あとで後悔することのないよう、念のため用意しておきましょう。

メーリングリストに参加するもともと、FreeBSD-STABLE と FreeBSD-CURRENT のコードブランチは、 開発中のものです。 FreeBSD の作業に貢献してくださっている人達も人間ですから、 時にはミスをすることだってあるでしょう。

そのような間違いは、単に警告を示す見慣れない 診断メッセージをシステムが、表示するような、 全く害のないものであることもあれば、システムを起動できなくしたり、 ファイルシステムを破壊してしまうような、 恐ろしい結果を招くものかも知れません。

万が一、このような問題が生じた場合、 問題の詳細と、どのようなシステムが影響を受けるかについて書かれた “注意 (heads up)” の記事が 適切なメーリングリストに投稿され、そして、その問題が解決されると、 “問題解決 (all clear)” のアナウンス記事が同様に 投稿されます。

FreeBSD-STABLE や FreeBSD-CURRENT ブランチに追随するために試そうとするのに、 FreeBSD-STABLE メーリングリストFreeBSD-CURRENT メーリングリスト を過去にさかのぼって読まないというのは、 自ら災難を招くことになるでしょう。

訳注: これらのメーリングリストは英語でやりとりされているため、 日本語での投稿は歓迎されません。英語でのやりとりができない人は、 FreeBSD 友の会 の運営しているメーリングリストをあたってみるのがいいでしょう。

make world は使わないこと古いドキュメントの多くが、この目的に make world を使うことを薦めています。 これは、重要な手順をいくつか抜かしてしまうので、 何をしているかよく分かっていなければ使うべきではありません。 ほぼあらゆる場合において、make world を実行するのは間違っており、 ここで説明されている手順を用いるべきです。

18.7.1. システムを更新する正式な方法

システムを更新する前に、 /usr/src/UPDATING を読んでください。 このファイルには、用意したソースコードで buildworld を行う前に必要な手順が書かれています。 その後、以下の手順を踏んでください。

この節で説明するアップデートのプロセスは、古いコンパイラ、 古いカーネル、古い world、そして古いコンフィグレーションファイルからなる、 古いバージョンの FreeBSD をアップデートすることを想定しています。 ここで “world” は、コアシステムのバイナリ、ライブラリ、 プログラミングファイルを意味します。 コンパイラは “world” の一部ですが、 いくつか特別に気をつけなければならないことがあります。

また、新しいシステムのソースをすでに入手していることも仮定しています。 もしシステムのソースコードが古いようでしたら、 項18.6 を読んで、 ソースコードを新しいバージョンへ同期する方法の詳細を理解してください。

ソースからのシステムのアップデートは、 当初予想していたものよりとらえがたいものです。 長い年月において避けられない依存問題が判明したため、 FreeBSD の開発者達は、推奨されるアプローチを大きく変更しました。 この節では、現在推奨されているアップグレードの手順の背後にある、 理論的根拠について説明します。

連続したアップデートの手順は、以下の問題に対応している必要があります。

これら 2 つの重要事項は、 以下の説明で中心となる buildworld, buildkernel, installkernel, installworld の基本です。 現在推奨されているアップグレードプロセスを採用したほうが良いという理由をすべて含んでいるわけではありません。 以下では、もう少し明確ではない点についてリストアップします。

これらを配慮し、以下の推奨手順が作られました。 アップデートの細かい手順においては、追加の手順が必要になるかもしれませんが、 この中心となるプロセスは、しばらくの間変わっていません。

  1. make buildworld

    新しいコンパイラと関連ツールを最初にコンパイルし、 その後、新しいコンパイラで、 新しい world の残りの部分をコンパイルします。 コンパイルされたものは、 /usr/obj に格納されます。

  2. make buildkernel

    config(8)make(1) を用いた古い方法とは異なり、 /usr/obj にある 新しい コンパイラが用いられます。 これにより、コンパイラとカーネルのミスマッチを防ぐことができます。

  3. make installkernel

    新しくアップデートされたカーネルで起動できるように、 新しいカーネルとカーネルモジュールをディスク上に配置します。

  4. シングルユーザモードで再起動

    シングルユーザモードは、 すでに実行されているソフトウェアをアップデートする際の問題を最小限にします。 また、新しいカーネル上で古い world が実行される際の問題も最小限にします。

  5. mergemaster -p

    新しい world における最初の設定ファイルのアップデートを行います。 たとえば、新しいユーザグループをシステムに追加したり、 パスワードデータベースに対し、新しいユーザ名を追加するかもしれません。 前回のアップデート後に、 新しいグループや特別のシステムのユーザアカウントが追加された場合に、 installworld のステップで、 新しくインストールされたシステムのユーザまたはシステムのグループ名を問題なく使うことができるように、 この作業がときどき必要となります。

  6. make installworld

    world を /usr/obj からコピーします。 これで、ディスクには新しいカーネルと world が置かれたことになります。

  7. mergemaster

    ディスクに新しい world が置かれたので、 残りの設定ファイルをアップデートします。

  8. 再起動

    新しいカーネル、world そして設定ファイルがロードされたので、 再起動が必要です。

もし、FreeBSD のあるブランチのあるリリースから、 同じブランチの最新リリースにアップデートするのであれば (たとえば 7.0 から 7.1)、 この手順にしたがわなくても良いでしょう。 なぜならば、コンパイラ、カーネル、ユーザランド、そして設定ファイルの間で、 重度のミスマッチが起きることはあまり考えられないためです。 マイナーなアップデートでは、新しいカーネルの構築とインストール後に、 古いアプローチである make world を用いてもうまくいくでしょう。

しかしながら、メジャーリリースをまたいだアップデートでは、 この方法を用いないと、何らかの問題にぶつかるでしょう。

大きなアップグレード (たとえば �4.X から 5.0 へのアップデート) においては、(たとえば installworld の前に特定のファイルの名前の変更や削除などの) 特別な追加のステップも必要となるでしょう。 /usr/src/UPDATING ファイルを注意深く読んでください。 特にファイルの最後には、 現在推奨されているアップグレードの手順が詳しく正確に説明されています。

この手続きは、 開発者たちがある種のミスマッチを完全に避けるために、長い年月をかけて進化してきました。 願わくば、この現在の手順が長い間安定してほしいものです。

まとめると、現在、ソースからの FreeBSD のアップグレードにおいて推奨されている方法は以下となります。

# cd /usr/src
# make buildworld
# make buildkernel
# make installkernel
# shutdown -r now

注意: まれに buildworld の前に mergemaster -p を余分に実行することが必要な場合があります。その場合は UPDATING にそう書かれています。 FreeBSD のメジャーバージョンをまたいで更新するのでなければ、 通常はこの手順を省略してもなんら問題ないでしょう。

installkernel が無事に終了したら、(たとえば、ローダのプロンプトから boot -s を使って) シングルユーザモードで立ち上げましょう。 それから、以下を実行してください。

# mount -u /
# mount -a -t ufs
# adjkerntz -i
# mergemaster -p
# cd /usr/src
# make installworld
# mergemaster
# reboot

この後の説明を読んでください上述の手順は、 とりあえず着手するための簡単なまとめにすぎません。 それぞれの手順をきちんと理解するために、 この後の節を読んでください。 カスタムカーネルを利用したいと考えているならなおさらです。

18.7.2. /usr/src/UPDATING を読む

何を始めるにしろ、まず最初に /usr/src/UPDATING (もしくはあなたがソースコードを どこにコピーしたにせよそれに相当するファイル) を読みましょう。 このファイルにはあなたが遭遇するかも知れない問題に対する重要な情報を 含んでいたり、あなたが特定のコマンドを実行しなければならなくなった時 その順序を指示したりするはずです。 UPDATING があなたが読んだ事柄と矛盾している時は UPDATING が優先します。

重要項目: UPDATING を読むということは、前述の 適切なメーリングリストを購読する代わりにはなりません。 二つの要求は相補的なもので排他的なものではないのです。

18.7.3. /etc/make.conf の確認

まず、/usr/share/examples/etc/make.conf/etc/make.conf を調べてください。 最初のファイルには、デフォルトの定義 (多くのものはコメントアウトされています) が含まれています。 これらを設定してソースからシステムを再構築するには、 変数の定義を /etc/make.conf に付け加えてください。 /etc/make.conf に追加された設定は、 make を実行するときに常に適用されるので、 システムに必要な設定を書いておくと良いでしょう。

標準的なユーザなら、 /usr/share/examples/etc/make.confNO_PROFILE 行を /etc/make.conf にコピーし、 コメントをはずすと良いでしょう。

NOPORTDOCS など、他の定義についても、 コメントを外す必要があるかどうか調べておきましょう。

18.7.4. /etc にあるファイルの更新

/etc ディレクトリには、 システム起動時に実行されるスクリプトだけでなく、 あなたのシステムの設定に関連する情報の大部分が 含まれています。そのディレクトリに含まれる スクリプトは、FreeBSD のバージョンによって多少異なります。

また、設定ファイルのなかには、稼働中のシステムが日々利用している ものもあります。実際には、/etc/group などがそれに該当します。

make installworld によるインストールの段階では、 特定のユーザ名、あるいはグループが存在していることを 要求する場面があります。システムのアップグレードを行なう際には、 それらのユーザ名やグループが削除、あるいは変更されて存在していない可能性が 考えられますが、そういった場合、システムのアップグレードを 行なっている間に、問題が発生する原因になります。 make buildworld において、 それらのユーザ名やグループが存在するか確認が行われる場合もあります。

この例の一つは、 smmsp ユーザが追加された時です。 mtree(8)/var/spool/clientmqueue を作成しようとする時、 そのユーザ名 (およびグループ) が存在しないためにインストールに失敗してしまったのです。

解決方法は、buildworld の前に -p オプションをつけて mergemaster(8) を実行することです。 これを実行すると、buildworldinstallworld が成功するために必要なファイルだけを比較します。

ティップ: もし、あなたがもっと神経質な人なら、あなたが名前を変更したり、 削除してしまったグループが所有しているファイルを、 次のようにして調べることもできます。

# find / -group GID -print

これは GID (グループ名もしくは数字で示されたグループ ID) で 指定されたグループが所有するすべてのファイルを表示します。

18.7.5. シングルユーザモードへの移行

コンパイルは、シングルユーザモードで行なった方が良いでしょう。 そうすることで多少速度が向上する、というちょっとした利点が あるだけでなく、システムの再インストールは重要なシステムファイル、 標準コマンド、ライブラリ、インクルードファイルなどを操作します。 稼働中のシステムに (特に他のユーザがそのシステムにログインしている時に) そのような変更を加えることは、トラブルを引き起こす原因となります。

もう一つの方法として、マルチユーザモードでシステムを再構築して、 シングルユーザモードに移行してからそれをインストールする、 というのがあります。もしこのような方法で行ないたい場合は、 以下の手順を構築が完了するところまで飛ばしてください。 シングルユーザモードに移行するのを、 installkernel もしくは installworld しなければならなくなるま で後回しにできます。

稼働中のシステムでシングルユーザモードに移行するには、 スーパユーザ (root) 権限で次のコマンドを実行します。

# shutdown now

あるいはシステムを再起動し、ブートプロンプトから “single user” を選択すると、 シングルユーザモードでシステムを起動できます。 起動後、シェルプロンプトから次のように実行してください。

# fsck -p
# mount -u /
# mount -a -t ufs
# swapon -a

これはファイルシステムをチェックした後、 / を読み書き可能にして再マウント、 /etc/fstab に指定されている、 それ以外の UFS ファイルシステムをすべてマウントしてから スワップを有効にします。

注意: CMOS クロックが地域時間に設定されていて GMT ではない場合 (date(1) コマンドが正しい時間と地域 を表示しないなら当てはまります)、 次のコマンドを実行する必要があるかもしれません。

# adjkerntz -i

こうすれば、 確実に地域時刻が正しく設定されます — これを怠ると、 あとあと問題になるかもしれません。

18.7.6. /usr/obj の削除

システムが再構築される時、構築されたものは (デフォルトで) /usr/obj 以下のディレクトリに格納され、 そのディレクトリの下は /usr/src と同じ構造となります。

このディレクトリをあらかじめ削除しておくことにより、 make buildworld の行程にかかる時間を短縮させ、 依存問題に悩まされるようなトラブルを回避することができます。

/usr/obj 以下のファイルには、 変更不可 (immutable) フラグ (詳細は chflags(1) 参照) がセットされているものがある可能性があります。 そのため、まず最初にそのフラグを変更しなければなりません。

# cd /usr/obj
# chflags -R noschg *
# rm -rf *

18.7.7. ベースシステムの再構築

18.7.7.1. 出力メッセージの保存

実行される make(1) からの出力は、ファイルに保存すると良いでしょう。 もし、何か障害が発生した場合、エラーメッセージのコピーを手元に残すことができます。 何が悪かったのか、あなた自身がそれから理解することはできないかも 知れませんが、FreeBSD メーリングリストに投稿して、 誰か他の人からの助言を得るために利用することができます。

ファイルに保存する最も簡単な方法は、script(1) コマンドを 使い、引数に出力を保存したいファイル名を指定することです。 これを make world の直前に行ない、再構築が終了してから exit と入力すると、出力を保存することができます。

# script /var/tmp/mw.out
Script started, output file is /var/tmp/mw.out
# make TARGET
… compile, compile, compile …
# exit
Script done, …

出力を保存する場合、/tmp ディレクトリの中に 保存してはいけません。 このディレクトリは、次の再起動で削除されてしまう可能性があります。 出力の保存には、(上の例のように) /var/tmproot のホームディレクトリが適しています。

18.7.7.2. ベースシステムの構築

まず、カレントディレクトリを /usr/src に 変更しなければなりません。次のように実行してください。

# cd /usr/src

(もちろん、ソースコードが他のディレクトリにある場合には、 /usr/src ではなく、 ソースコードのあるディレクトリに移動してください)。

make world を行なうには、make(1) コマンドを使用します。 このコマンドは、Makefile というファイルから、 FreeBSD を構成するプログラムの再構築方法や、 どういう順番でそれらを構築すべきかといったような 指示を読み込みます。

コマンドラインの一般的な書式は、次のとおりです。

# make -x -DVARIABLE target

この例では、-xmake(1) に渡されるオプションになります。 どのようなオプションが利用できるかについては、マニュアルページを 参照してください。

-DVARIABLE は、 Makefile に渡される変数であり、 この変数は Makefile の動作をコントロールします。 また、/etc/make.conf で設定される変数も 同様です。これは変数を設定するもう一つの方法として用意されています。

# make -DNO_PROFILE target

は、プロファイル版のライブラリを構築しないことを指定する もう一つの記法で、/etc/make.conf 中の

NO_PROFILE=    true 	#    Avoid compiling profiled libraries

の行に対応します。

target は、make(1) に どのように動作するのかを指示するためのものです。 各々の Makefile には、数多くの異なる “ターゲット (target)” が定義されていて、 指定されたターゲットによって動作が決まります。

Makefile に書かれているターゲットには、 あなたが指定しても意味を持たないものも含まれます。 これらは、システムの再構築に必要な段階を、多くの さらに細かい段階に分割するため、構築の過程で利用されるものです。

大抵の場合、make(1) にパラメータを指定する必要はないでしょうから、 コマンドラインは次のようなものになるでしょう。

# make target

ここで、target は、多くのビルドオプションのどれかになります。 最初のターゲットはいつも buildworld になるでしょう。

その名前が示すように、buildworld/usr/obj 以下に新しい完全な ディレクトリツリーを構築し、もう一つのターゲット installworld は、そのツリーを 現在のマシンにインストールします。

選択肢が分けられていることは、二つの理由から非常に有用です。 まず第一に、稼働中のシステムに全く影響を与えることなく、 安全にシステムの構築作業を行えることです。 構築作業は “何にも依存せず独立して行なわれる” ため、 マルチユーザモードで稼働中のシステムでも、何一つ 悪影響を与えずに buildworld を 実行することができます。 ただし、installworld は シングルユーザモードで行なうことをおすすめします。

第二に、NFS マウントを利用することで、 ネットワーク上の複数のマシンをアップグレードすることが 可能な点があげられます。たとえば三台のマシン、 A, B, C をアップグレードしたい場合には、まずマシン Amake buildworldmake installworld を実行します。 それから、マシン B とマシン C でマシン A/usr/src/usr/obj を NFS マウントし、make installworld とすることで 構築済みのシステムを各マシンにインストールすることができるのです。

world ターゲットも利用可能ですが、 このターゲットの利用は推奨されていません。

次のコマンド

# make buildworld

を実行してください。ここで make-j オプションをつけると、 同時にいくつかのプロセスを生成させることができます。 この機能はマルチ CPU マシンで特に効果を発揮します。 構築過程の大部分では CPU 性能の限界より I/O 性能の限界の方が問題となるため、シングル CPU マシンにも効果があります。

普通のシングル CPU マシンで以下のコマンド

# make -j4 buildworld

を実行すると、make(1) は最大 4 個までのプロセスを同時に実行します。 メーリングリストに投稿された経験的な報告によると、 4 個という指定が最も良いパフォーマンスを示すようです。

もし、複数の CPU を備えたマシンで SMP 設定が行なわれたカーネルを 利用しているなら、6 から 10 の間の値を設定し、速度がどれくらい 向上するか確認してみてください。

18.7.7.3. システムの構築にかかる時間

構築時間を決める要素はさまざまありますが、 十分新しいマシンであれば、 トリックや近道を使わずに普通に構築した場合、FreeBSD-STABLE の構築には 1, 2 時間しかかからないでしょう。 FreeBSD-CURRENT の構築は、もう少し時間がかかります。

18.7.8. 新しいカーネルの構築とインストール

新しいシステムの全機能を完全に利用できるようにするには、 カーネルの再構築をする必要があります。 再構築は、ある種のメモリ構造体が変更された時には特に必須であり、 ps(1)top(1) のようなプログラムは、 カーネルとソースコードのバージョンが一致しないと正常に動作しないでしょう。

最も簡単で安全にカーネルの再構築を行なう方法は、 GENERIC を使ったカーネルを構築・インストールすることです。 GENERIC にはあなたが必要とするデバイスがすべて含まれていない かも知れませんが、あなたのシステムをシングルユーザモードで 起動させるのに必要なものはすべて入っています。 これは新しいバージョンのシステムがきちんと動作するかどうか 調べる良い方法の一つです。 GENERIC で起動してから、 あなたがいつも使っているカーネルコンフィグレーションファイルを 使って新しいカーネルを構築することで、 システムが正常に動作しているかどうか確かめることができます。

FreeBSD では、新しいカーネルを構築する前に build world を行うことが重要です。

注意: カスタムカーネルを構築したい場合、既にコンフィグレー ションファイルがあるならば、単に KERNCONF=MYKERNEL を使ってください。

# cd /usr/src
# make buildkernel KERNCONF=MYKERNEL
# make installkernel KERNCONF=MYKERNEL

なお、kern.securelevel を 1 より大きく していて、かつカーネルのバイナリファイル に noschg のようなフラグを設定している場合 は、installkernel を行うのにシングル ユーザモードに移行しなければなりません。それ以外の場合は、マル チユーザモードでこれらのコマンドを問題なく動かせるはずです。 kern.securelevel について詳しくは init(8) を、ファイルの様々なフラグについて詳しくは chflags(1) をご覧ください。

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

新しいカーネルが動作するかどうかテストするために、 シングルユーザモードで再起動するべきです。 シングルユーザモードでの起動は、 項18.7.5 に書かれている手順に従ってください。

18.7.10. 新しいシステムバイナリのインストール

次に、ここで installworld を使うことで新しいシステムバイナリのインストールを行ないます。

それには、以下のコマンドを実行してください。

# cd /usr/src
# make installworld

注意: make buildworld でコマンドラインから 変数を指定した場合は、同じ指定を make installworld のコマンドラインにも 指定しなければなりません。 ただし、オプションについてはその限りではありません。 たとえば -jinstallworld で絶対に使ってはいけません。

たとえば以下のように実行したなら、

# make -DNO_PROFILE buildworld

以下のようにしてインストールしなければなりません。

# make -DNO_PROFILE installworld

もしそうしなかった場合、 make buildworld の段階で構築されていない プロファイル版ライブラリをインストールしようとしてしまうでしょう。

18.7.11. make installworld で更新されないファイルの更新

システムの再構築は、いくつかのディレクトリ ( 特に、/etc/var/usr) において、 新規に導入されたり、変更された設定ファイルによる ファイルの更新は行なわれません。

これらのファイルを更新するもっとも簡単な方法は、mergemaster(8) を使うことです。これは自分でやることも可能なので、そうしても かまいません。 いずれの方法に従うにせよ、 必ず /etc のバックアップを取って不測の事態に備えてください。

18.7.11.1. mergemaster

寄稿: Tom Rhodes.

mergemaster(8) ユーティリティは Bourne シェルスクリプトで、 /etc にある設定ファイルとソースツリーの /usr/src/etc にある設定ファイルの違いを確認するのを手伝ってくれます。 これを使うのが、ソースツリーにある設定ファイルにシステムの設定ファイルを 更新するために推奨される方法です。

始めるには、プロンプトから単に mergemaster と入力して、 ファイルの比較を開始するのを見てください。 mergemaster/ を起点とした一時的なルート環境を構築し、 さまざまなシステム設定ファイルを (訳注: デフォルトでは /var/tmp/temproot に) 置いていきます。 次にこれらのファイルは現在システムにインストールされているファイルと比較されます。 この時点で、異なるファイルは diff(1) 形式で示され、 + の記号は追加または変更された行を表し、 - は完全に削除されたか新しく置き換えられた行を表します。 diff(1) の書式とファイルの違いの表示方法についてのより詳しい情報は、 diff(1) を参照してください。

mergemaster(8) は食い違いが起きているファイルをそれぞれ示します。 ここでは新しいファイル (一時ファイルとして参照されています) を削除するか、 一時ファイルをそのままインストールするか、 一時ファイルと現在インストールされているファイルを統合するか、 もしくは diff(1) の結果をもう一度見るか選択できます。

一時ファイルの削除を選ぶと、mergemaster(8) に現在のファイルを変更しないで新しいバージョンを削除せよと伝えます。 この選択は、現在のファイルを変更する理由が分からないのであれば、 お勧めできません。 mergemaster(8) のプロンプトで ? とタイプすれば、 いつでもヘルプが見られます。 ファイルのスキップを選ぶと、他のすべてのファイルを終えたあと、 もう一度そのファイルが提示されます。

一時ファイルをそのままインストールすることを選ぶと、 現在のファイルを新しいファイルで置き換えます。 ほとんどの手を加えていないファイルは、 これが一番よい選択です。

ファイルの統合を選んだ場合、 テキストエディタが起動され、両方のファイルの中身が提示されます。 画面上に並ぶ両方のファイルを見て新しいファイルを作成するために両方から必要な部分を選択し、 2 つのファイルを統合することができます。 並んでいるファイルを比較するとき、 l キーで左側の中身を選択し、 r キーで右側の中身を選択します。 最終出力は左右両方の部分でできたファイルになるでしょう。 このファイルをインストールすることができます。 たいてい、このオプシュンはユーザが設定を変更したファイルに使われます。

diff(1) の結果をもう一度見る、を選択すると、 ちょうど先ほど mergemaster(8) が選択肢を表示する前と同じように、 ファイルの相異点を見ることができます。

mergemaster(8) がシステムファイルの比較を終えたあと、 他のオプションについてもプロンプトが表示されます。 mergemaster(8) が、パスワードファイルを再構築したいかどうか尋ねることがあります。 最後に残った一時ファイルを削除するかどうかを尋ねて終了します。

18.7.11.2. 手動での更新

手動で更新することを選んだ場合、 単にファイルを /usr/src/etc から /etc に コピーしただけでは正常に動作させることはできません。 これらのファイルには、“インストールという 手順を踏まなければならないもの” が含まれています。 /usr/src/etc ディレクトリは /etc ディレクトリにそのまま置き換えられるような コピーではないからです。 また、/etc にあるべきファイルのうちで /usr/src/etc にないものもあります。

mergemaster(8) を (勧められた通り) 使っているのであれば、次の節 まで飛ばしてもかまいません。

手動で行う際の 一番簡単な方法は、ファイルを新しいディレクトリにインストールしてから、 以前のものと異なっている部分を調べて更新作業を行なうことです。

既存の /etc をバックアップする 理論的に考えて、このディレクトリが自動的に 処理されることはありませんが、念には念を入れておいて 損はありません。たとえば以下のようにして、 既存の /etc ディレクトリを どこか安全な場所にコピーしておきましょう。

# cp -Rp /etc /etc.old

-R は再帰的なコピーを行ない、 -p はファイルの更新時間や所有者などを保存します。

また、新しい /etc やその他のファイルを インストールするための、仮のディレクトリを作っておく必要があります。 仮ディレクトリは /var/tmp/root に置くのが良いでしょう。 同様に、必要なサブディレクトリもこの下に置きます。

# mkdir /var/tmp/root
# cd /usr/src/etc
# make DESTDIR=/var/tmp/root distrib-dirs distribution

上の例は、必要なディレクトリ構造をつくり、ファイルをインストールします。 /var/tmp/root 以下に作られる、 たくさんの空のディレクトリは削除する必要があります。 一番簡単なやり方は、次のとおりです。

# cd /var/tmp/root
# find -d . -type d | xargs rmdir 2>/dev/null

これは空ディレクトリをすべて削除します。 (空でないディレクトリに関する警告を避けるために、 標準エラー出力は /dev/null に リダイレクトされます)

この段階の /var/tmp/root には、 本来 / 以下にあるべきファイルが すべて含まれています。 各ファイルを順に見て、既存のファイルと異なる部分を 調べてください。

/var/tmp/root 以下に インストールされているファイルの中には、 “.” から始まっているものがあります。 これを書いている時点で、それに該当するファイルは /var/tmp/root//var/tmp/root/root/ の中にある シェルスタートアップファイルだけですが、 他にもあるかも知れません (これは、あなたがこれをどの時点で読んでいるかに依存します)。 ls -a を使って確かめてください。

もっとも簡単な方法は、二つのファイルを比較するコマンド diff(1) を使うことです。

# diff /etc/shells /var/tmp/root/etc/shells

これは、あなたの /etc/shells ファイルと 新しい /var/tmp/root/etc/shells ファイルの 異なる部分を表示します。 これらを、あなたが書き換えたものに変更点をマージするか、 それとも既存のファイルを新しいもので上書きするかを 判断する材料にしてください。

新しい root ディレクトリ (/var/tmp/root) の名前に タイムスタンプを付けておくと、 異なるバージョン間の比較を楽に行なうことができます。: 頻繁にシステムの再構築を行なうということは、 /etc の更新もまた、頻繁に行う必要がある ということです。これはちょっと手間のかかる作業です。

この作業は、あなたが /etc にマージした、 新しく変更されたファイルの最新のセットのコピーを保存しておくことで 素早く行なうことができます。 下の手順は、それを実現するための一つの方法です。

  1. 普通に make world します。/etc や 他のディレクトリを更新したくなったときは、ターゲット ディレクトリに、そのときの日付に基づく名前をつけてください。 たとえば 1998 年 2 月 14 日 だとすれば、以下のようにします。

    # mkdir /var/tmp/root-19980214
    # cd /usr/src/etc
    # make DESTDIR=/var/tmp/root-19980214 \
        distrib-dirs distribution
    
  2. 上に説明されているように、 このディレクトリから変更点をマージします。

    その作業が終了しても、 /var/tmp/root-19980214 を 削除してはいけません

  3. 最新版のソースをダウンロードして再構築したら、 ステップ 1 にしたがってください。今度は、 /var/tmp/root-19980221 (更新作業が一週間おきだった場合) のような名前の、新しいディレクトリをつくることになるでしょう。

  4. この段階で diff(1) を使用し、 二つのディレクトリを比較する再帰的 diff を作成することで、 一週間の間に行なわれたソースへの変更による相違点を調べます。

    # cd /var/tmp
    # diff -r root-19980214 root-19980221
    

    これによって報告される相違点は、大抵の場合、 /var/tmp/root-19980221/etc/etc との場合に比べて 非常に少ないものになります。 相違点が少ないため、変更点を既存の /etc ディレクトリにマージすることは、比較的容易になります。

  5. ここまで終了したら、/var/tmp/root-* の 二つのうち、古い方のディレクトリは削除して構いません。

    # rm -rf /var/tmp/root-19980214
    
  6. この工程を、/etc へ変更点をマージする 必要があるたび、毎回繰り返します。

ディレクトリ名の生成を自動化するには、date(1) を利用することができます。

# mkdir /var/tmp/root-`date "+%Y%m%d"`

18.7.12. 再起動

これで、作業はおしまいです。 すべてがあるべき正しい場所に存在することをチェックしたら、 システムを再起動します。これは、単に shutdown(8) を実行するだけです。

# shutdown -r now

18.7.13. 作業の完了

ここまで来れば、FreeBSD システムのアップグレードは成功です。 おめでとうございます。

もしちょっとした問題があった場合でも、 システムの一部を再構築するのは簡単です。 たとえば、アップグレードの途中で誤って /etc/magic を削除して /etc にマージしてしまい、 その結果 file コマンドが動作しなくなってしまったような場合を考えてみてください。 これを修復するには、次のコマンドを実行すれば修復することができます。

# cd /usr/src/usr.bin/file
# make all install

18.7.14. 質問ですか?

18.7.14.1. 変更が行なわれたら、その度にシステムの再構築が必要になるのでしょうか?
18.7.14.2.
18.7.14.3. 終了したら /usr/obj を削除しても かまいませんか?
18.7.14.4. 構築を中断した場合、その構築を途中から再開することはできますか?
18.7.14.5. どのようにすれば make world を高速化できますか?
18.7.14.6. なにか悪いことがあったらどうすればいいですか?

18.7.14.1. 変更が行なわれたら、その度にシステムの再構築が必要になるのでしょうか?

それは変更の性質によるので、なんとも言えません。 たとえば、CVSup を実行したとき、最後に実行したときから比べて 次にあげるようなファイルが更新されていたとします。

src/games/cribbage/instr.c
src/games/sail/pl_main.c
src/release/sysinstall/config.c
src/release/sysinstall/media.c
src/share/mk/bsd.port.mk

このときには、改めてシステム全体を再構築する必要はないでしょう。 適切なサブディレクトリに移って make all install を行うだけで更新することができます。 しかし、もし何らかの大きな変更が行なわれているとき、たとえば src/lib/libc/stdlib が変更されている場合には、 システム全体を再構築するか、もしくはそのうち、 少なくとも静的にリンクされているもの (と、あなたが追加した 静的にリンクされたプログラム) を作り直す必要があります。

結局のところ、どの時点で現在のシステムをアップグレードするかは あなたが決めることです。 2 週間ごとにシステムを再構築し、その 2 週間の変更を取り込めば 幸せかもしれませんし、 変更のあった部分だけ再構築し、依存関係を確かめたいと考えるかも知れません。

もちろん、それらはどのくらいの頻度でアップグレードしたいか、 そして FreeBSD-STABLE か FreeBSD-CURRENT のどちらを追いかけているのかによります。

18.7.14.2.

signal 11 (もしくは他のシグナル番号) のエラーがたくさん出て コンパイルが失敗します。何が起こっているんでしょうか?

これは通常、ハードウェアに問題があることを示しています。 システムの再構築は、ハードウェアに対する負荷耐久試験を行なうための 有効な手段の一つで、メモリに関係する問題がよく報告されます。 その大部分は、コンパイラが奇妙なシグナルを受け取り、 不可解な異常終了となることで発見されます。

本当にこの問題によるものかどうかは、再構築をもう一度実行し、 異なる段階で異常終了が発生するか、ということから確認できます。

この場合には、マシンの部品を交換して、どの部分が悪いのかを 調べてみることくらいしかできることはありません。

18.7.14.3. 終了したら /usr/obj を削除しても かまいませんか?

一言で答えるなら「削除しても構わない」です。

/usr/obj には、 コンパイルの段階で生成された すべてのオブジェクトファイルが含まれています。 通常 make buildworld の最初の段階では、 このディレクトリを削除して新しくつくり直すようになっています。 その場合には、構築終了後の /usr/obj を保存しておいても、あまり意味はありません。 削除すれば、大きなディスクスペースを (現在はだいたい 2�GB あります) 解放することができます。

しかし、もしあなたが何を行なおうとしているのか理解しているなら、 この段階を省略して make buildworld を行なうことができます。 こうすると、ほとんどのソースは再コンパイルされないため、 構築はかなり高速化されます。 これは裏をかえせば、デリケートな依存関係の問題によって、 システムの構築が奇妙な失敗に終わる可能性があるということです。 FreeBSD メーリングリストではしばしば、構築の失敗が、 この段階の省略によるものだということを理解せずに 不満の声をあげる人がいます。

18.7.14.4. 構築を中断した場合、その構築を途中から再開することはできますか?

それは、あなたが問題に気付く前に、 どれだけの作業を終えているかによって変わります。

一般的に (そしてこれは確実でしっかりした 規則ではありませんが)、 make buildworld の過程では、 基本的なツール ( gcc(1)make(1) のようなもの) や、システムライブラリの新しいコピーが作成されます。 その後まず、これらのツールやライブラリはインストールされてから 自分自身の再構築に使われ、もう一度、インストールされます。 全体のシステム (ここでは ls(1)grep(1) といった 標準的なユーザプログラムを含みます) は、 その新しいシステムファイルを用いて作り直されることになります。

もし、再構築が最終段階に入っていること が (記録しておいた出力を見たりすることで) わかっていたら、 (全く悪影響を与えることなく) 次のようにすることができます。

… fix the problem …
# cd /usr/src
# make -DNO_CLEAN all

これは、前回の make buildworld の作業をやり直しません。

次のメッセージ

--------------------------------------------------------------
Building everything..
--------------------------------------------------------------

make buildworld の出力にある場合には、 上のようにしてもほとんど悪影響が現れることはありません。

もしこのメッセージがないとか、よく分からないという場合には、 安全を確保し、後悔するようなことがないよう、 システムの再構築を最初からやり直しましょう。

18.7.14.5. どのようにすれば make world を高速化できますか?

  • シングルユーザモードで動かしてください。

  • /usr/src/usr/obj ディレクトリを、 異なるディスク上の別のファイルシステムに置いてください。 また可能ならば、異なるディスクコントローラに接続された ディスクを使ってください。

  • さらに高速化するには、これらのファイルシステムを ccd(4) (連結ディスクドライバ) デバイスを 使って、複数のディスク上に置いてください。

  • プロファイル版の作成を無効化してください。 (/etc/make.conf で “NO_PROFILE=true” をセットします) 普通、それが必要になることはありません。

  • make(1)-jn オプ ションを指定して、複数のプロセスを並列に実行させてく ださい。 これはプロセッサが単一か複数かによらず、 どちらも同様に恩恵を得ることができます。

  • /usr/src のある ファイルシステムを、noatime オプションを付けてマウント (もしくは再マウント) してください。 これは、そのファイルシステムにおいて、 最後にアクセスされた時刻の書き込みを抑制します。 おそらく、この情報が必要になることはないでしょう。

    # mount -u -o noatime /usr/src
    

    警告上の例は、 /usr/src 自身が独立したファイルシステムで あることを想定しています。 もしそうでないときには (たとえば /usr の 一部である場合には)、 /usr/src ではなく 適切なマウントポイントを指定する必要があります。

  • /usr/obj のあるファイルシステムを、 async オプションをつけてマウント (もしくは 再マウント) してください。これによって、 ディスクへの書き込みが非同期になります。 つまり、書き込み命令はすぐに完了するのに対し、 実際にデータがディスクに書き込まれるのは、その数秒後になります。 これによって、書き込み処理の一括化が可能になるため、 劇的なパフォーマンスの向上が期待できます。

    警告 このオプションを指定すると、ファイルシステムは 壊れやすくなってしまうことに注意してください。 このオプションを付けていて、突然電源が落ちた場合には、 再起動後にファイルシステムが復旧不能になる可能性が 非常に高くなります。

    もし、/usr/obj 自身が独立した ファイルシステムであるならば、これは問題になりません。 しかし、同じファイルシステムに、他の貴重なデータを置いているときには、 このオプションを有効にする前に、 バックアップをきちんと取っておきましょう。

    # mount -u -o async /usr/obj
    

    警告もし /usr/obj 自身が ファイルシステムでない場合には、適切なマウントポイントを指すように、 上の例の名前を置き換えてください。

18.7.14.6. なにか悪いことがあったらどうすればいいですか?

自分の環境に前のビルドの余計なゴミが残っていないことをはっきりと確認してください。 とても簡単です。

# chflags -R noschg /usr/obj/usr
# rm -rf /usr/obj/usr
# cd /usr/src
# make cleandir
# make cleandir

ええ、make cleandir は本当に 2 回実行するのです。

そして、make buildworld を行い、 全プロセスを最初からやり直してください。

まだ問題があれば、エラーと uname -a の出力を FreeBSD general questions メーリングリスト に送ってください。 自分の設定についてさらに質問されても答えられるよう用意してください!

本文書、および他の文書は ftp://ftp.FreeBSD.org/pub/FreeBSD/doc/ からダウンロードできます。

FreeBSD に関する質問がある場合には、ドキュメント を読んだ上で <[email protected]> まで (英語で) 連絡してください。
本文書に関する質問については、<[email protected]> まで電子メールを (英語で) 送ってください。