FreeBSD ハンドブック
Prev | Chapter 17. 開発の最前線 | Next

# 17.4. “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` を実行するのは間違っており、 ここで説明されている手順を用いるべきです。

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

システムを更新するには、次の手順を踏むべきです。

    # make buildworld
    # make buildkernel
    # make installkernel
    # reboot

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

    # mergemaster -p
    # make installworld
    # mergemaster
    # reboot

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

## 17.4.2. `/usr/src/UPDATING` を読む

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

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

## 17.4.3. `/etc/make.conf` の確認

まず、`/usr/share/examples/etc/make.conf` (FreeBSD 4.X では `/etc/defaults/make.conf`) と `/etc/make.conf` を調べてください。そこには 最初から標準的なものが (多くのものはコメントアウトされていますが) 含まれています。ソースからシステムを再構築するときに make が `/etc/make.conf` に付け加えられた設定を使用します。 `/etc/make.conf` に追加された設定は `make` を実行したときに常に使われることを覚えておいてください。 そのため、システムに必要な設定を書いておくと良いでしょう。

標準的なユーザならおそらく、 `/usr/share/examples/etc/make.conf` (FreeBSD 4.X では `/etc/defaults/make.conf`) の `CFLAGS` と `NOPROFILE` のコメントをはずすことを考えると思います。

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

## 17.4.4. `/etc` にあるファイルの更新

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

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

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

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

解決方法は、`/usr/src/etc/group` を調べ、 自分のシステムのグループ名リストと比較することです。 最新のファイルに含まれていて、あなたのファイルに含まれていない グループ名があれば、あなたのファイルにそのグループ名をコピーしてください。 同様に、名前が異なるにも関わらず、 `/etc/group` と `/usr/src/etc/group` で同じ GID を持っているグループ名があれば、 `/etc/group` に含まれる、 該当するすべてのグループ名を変更しておかなければなりません。

4.6-RELEASE からは、buildworld の前に `-p` をつけて mergemaster(8) を実行してもよいです。 これを実行すると、`buildworld` や `installworld` が成功するために必要なファイルだけを比較します。 古いバージョンの `mergemaster` を使っていて、`-p` がサポートされていない場合、 最初に実行するときソースツリーにある新しいバージョンのものを使ってください。

    # cd /usr/src/usr.sbin/mergemaster
    # ./mergemaster.sh -p

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

>     # find / -group GID -print

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

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

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

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

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

    # shutdown now

あるいはシステムを再起動し、ブートプロンプトから `-s` フラグを設定することで、シングルユーザモードで システムを起動させることができます。起動後、シェルプロンプトから 次のように実行してください。

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

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

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

>     # adjkerntz -i

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

## 17.4.6. `/usr/obj` の削除

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

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

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

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

## 17.4.7. ソースの再構築

### 17.4.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/tmp`や `root` のホームディレクトリが適しています。

### 17.4.7.2. ベースシステムの構築

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

    # cd /usr/src

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

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

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

    # make -x -DVARIABLE target

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

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

    # make -DNOPROFILE target

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

    NOPROFILE=    true     #    Avoid compiling profiled libraries

の行に対応します。

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

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

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

    # make target

FreeBSD の 2.2.5 から (実際には、FreeBSD-CURRENT ブランチで最初に作成され、 2.2.2 と 2.2.5 の間の時点で FreeBSD-STABLE に導入されたのですが)、 `world` ターゲットは `buildworld` と `installworld` の二つに分割されました。 `world` ターゲットは、 ほとんどのユーザにとっては実際に危険なものなので、FreeBSD バージョン 5.3 からは全く動かないように変更されます。

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

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

第二に、NFS マウントを利用することで、 ネットワーク上の複数のマシンをアップグレードすることが 可能な点があげられます。たとえば三台のマシン、 `A`, `B`, `C` をアップグレードしたい場合には、まずマシン `A` で `make buildworld` と `make 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 の間の値を設定し、速度がどれくらい 向上するか確認してみてください。

ただし、この機能はまだ実験段階であるということに注意してください。 そのため、ソースツリーへ変更が加えられたときに これが正常に機能しなくなる可能性があります。 もし、このオプションを用いてシステムの構築に失敗した場合には、 障害を報告する前に、もう一度オプションを付けずに試してみてください。

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

構築時間を決める要素はさまざまありますが、 現時点では Pentium III の 500 MHz、128 MB の RAM という構成でトリックや近道を使わずに普通に構築した場合、 FreeBSD-STABLE の構築に約 2 時間かかります。 FreeBSD-CURRENT の構築は、もう少し時間がかかります。

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

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

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

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

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

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

> FreeBSD 4.2 以前では、 `KERNCONF=` を `KERNEL=` に置き換えなければなりません。2001 年 2 月 2 日以前に取得した 4.2-STABLE では `KERNCONF=` を認識しません。

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

FreeBSD の 4.0 以前にアップグレードする場合は、 古いカーネル構築手順に従う必要があります。 ただし、以下のコマンドを使って新しいバージョンの config(8) を利用することが推奨されています。

    # /usr/obj/usr/src/usr.sbin/config/config KERNELNAME

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

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

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

十分最近のバージョンの FreeBSD を `make buildworld` で構築しているなら、 次にここで `installworld` を 使うことで新しいシステムバイナリのインストールを行ないます。

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

    # cd /usr/src
    # make installworld

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

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

>     # make -DNOPROFILE buildworld

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

>     # make -DNOPROFILE installworld

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

## 17.4.11. `make installworld` で更新されないファイルの更新

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

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

### 17.4.11.1. `mergemaster`

寄稿: Tom Rhodes.

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

`mergemaster` は 3.3-RELEASE と 3.4-RELEASE の間に FreeBSD のベースシステムに統合されました。 つまり、3.3 以降の -STABLE と -CURRENT のシステムにはすべて これがあるということです。

始めるには、プロンプトから単に `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) が、パスワードファイルを再構築したいかどうかや、 FreeBSD 5.0 より前のバージョンを動かしている場合は MAKEDEV(8) を実行するかどうかを尋ねることがあります。 最後に残った一時ファイルを削除するかどうかを尋ねて終了します。

### 17.4.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"`

## 17.4.12. `/dev` の更新

> Note: FreeBSD 5.0 以降を利用しているなら、この節は飛ばし て構いません。それらのバージョンでは、devfs(5) を利用し てデバイスノードをユーザに意識させずに割り当てています。

ほとんどの場合、mergemaster(8) は デバイスノードの再構築が必要であることを検出して自動的にそれを 実行するのですが、ここではデバイスノードの再構築を手動で行なう 方法について説明します。

安全のため、これはいくつかの段階に分けて行ないます。

1. `/var/tmp/root/dev/MAKEDEV` を `/dev` にコピーします。

       # cp /var/tmp/root/dev/MAKEDEV /dev

   `/etc` を更新するのに mergemaster(8) を使った場合、 `MAKEDEV` スクリプトは既に更新 されているでしょうが、(diff(1) を使って) チェックすることは無駄ではありませんし、 必要なら自分でコピーしてください。

2. ここで、`/dev` のファイル一覧を記録しておきます。 この一覧は、各ファイルの許可属性、所有者、メジャー番号、マイナー番号が 含まれている必要がありますが、タイムスタンプは含まれていてはいけません。 これを行なう簡単な方法は、awk(1) を使って、 いくつかの情報を取り除くことです。

       # cd /dev
       # ls -l | awk '{print $1, $2, $3, $4, $5, $6, $NF}' > /var/tmp/dev.out

3. デバイスノードをつくり直します。

       # sh MAKEDEV all

4. もう一度、ディレクトリのファイル一覧を記録します。 今回は `/var/tmp/dev2.out` です。 この段階で、この二つのファイル一覧を調べて 作成に失敗したデバイスノードを探してください。 違いは一つもないはずなのですが、安全のために一応チェックしてください。

       # diff /var/tmp/dev.out /var/tmp/dev2.out

   次のようなコマンドを使用し、ディスクスライスエントリを 再作成することで、ディスクスライスの矛盾を検出することがで きます。

       # sh MAKEDEV sd0s1

   適当な組み合わせは、環境によって異なります。

## 17.4.13. `/stand` の更新

> Note: この段階は、完全な更新を行なう場合にだけ必要な内容を含んでいます。 悪影響はありませんので、省略しても構いません。 FreeBSD 5.2 以降を利用しているなら、 `make installworld` の際に、ユーザのために、 `/rescue` ディレクトリが、静的コンパイル されたその時点のバイナリで更新されます。ですから、 `/stand` を更新する必要はありません。

完全な更新を行なうために、 `/stand` にあるファイルも同じように 更新したいと考えるかも知れません。 これらのファイルは、`/stand/sysinstall` という バイナリファイルへのハードリンクです。このバイナリファイルは、 他のファイルシステム (特に `/usr`) が マウントされていない場合にも動作できるよう、 静的にリンクされていなければなりません。

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

## 17.4.14. 再起動

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

    # shutdown -r now

## 17.4.15. 作業の完了

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

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

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

## 17.4.16. 質問ですか?

17.4.16.1. 変更が行なわれたら、その度にシステムの再構築が必要になるのでしょうか?
17.4.16.2. signal 11 (もしくは他のシグナル番号) のエラーがたくさん出て コンパイルが失敗します。何が起こっているんでしょうか?
17.4.16.3. 終了したら `/usr/obj` を削除しても かまいませんか?
17.4.16.4. 構築を中断した場合、その構築を途中から再開することはできますか?
17.4.16.5. どのようにすれば make world を高速化できますか?
17.4.16.6. なにか悪いことがあったらどうすればいいですか?

17.4.16.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 のどちらを追いかけているのかによります。

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

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

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

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

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

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

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

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

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

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

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

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

    ... fix the problem ...
    # cd /usr/src
    # make -DNOCLEAN all

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

次のメッセージ

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

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

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

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

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

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

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

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

- また、`/etc/make.conf` の中の `CFLAGS` を、 `-O -pipe` のように指定しましょう。 `-O2` の最適化はさらに多くの時間を必要とし、 しかも `-O` と `-O2` の 最適化には、ほとんど差はありません。 `-pipe` を指定することで、 コンパイラはテンポラリファイルの代わりにパイプを利用します。 その結果、(メモリの利用は増えますが) ディスクアクセスが減ります。

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

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

      # mount -u -o noatime /usr/src

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

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

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

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

      # mount -u -o async /usr/obj

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

17.4.16.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 メーリングリスト に送ってください。 自分の設定についてさらに質問されても答えられるよう用意してください!

Prev | Home | Next
ソースの同期 | Up | 複数のマシンで追いかける