This is an archive of past FreeBSD releases; it's part of the FreeBSD Documentation Archive.

make world の利用

19.4. make world の利用

FreeBSD のどれか特定のバージョン (stable, current など) について, ローカルのソースツリーを同期させたら, そのソースツリーを使ってシステムを 再構築しなければなりません.

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

まず, バックアップがきちんと作成されていることを確認して下さい. そして, fix-it フロッピーを用意して下さい. 私は今までに, 一度もバックアップや fix-it フロッピーのお世話になったことはありませんし, これからもそうなるようなことはないと思っていますが, どういう場合であっても用意しておいて損はないでしょう.

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

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

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

-STABLE や -CURRENT ブランチを試したり, それらに 追随していくときに を読まないというのは, 自ら災難を招くことになるでしょう.

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

19.4.1. /usr/src/UPDATING を読む

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

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

19.4.2. /etc/make.conf の確認

まず, /etc/defaults/make.conf/etc/make.conf を調べてください. そこには 最初から標準的なものが (多くのものはコメントアウトされていますが) 含まれています. ソースからシステムを再構築するときに make が /etc/make.conf に付け加えられた設定を使用します. /etc/make.conf に追加された設定は make を実行したときに常に使われることを覚えておいてください. それらをあなたのシステムに合うように設定しておくとよいでしょう. ( FreeBSD 開発者でない) 標準的なユーザならおそらく /etc/defaults/make.confCFLAGSNOPROFILE の行を追加したいでしょう.

最初の状態では, すべてがコメントアウトされています. 必要だと思う項目のコメントをはずして下さい. (開発者でない)標準的なユーザならおそらく, CFLAGS と NOPROFILE のコメントをはずすことを考えると思います.

FreeBSD 2.1.7 以前の場合: もし, 浮動小数点演算ユニット(386DX, 486DX, Pentium と, それより上のクラスのマシン)がある場合には, HAVE_FPU の行のコメントをはずすことができます.

この定義は, FreeBSD 2.2.2 以降で廃止されました.

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

19.4.3. /etc/group の更新

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

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

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

この種の例でもっとも記憶に新しいのは, "ppp" グループ(後に "network" に変更されました)が 追加された時です. ppp サブシステムがインストールされる時, そのサブシステムが利用する "ppp" グループが存在しなかったために, それらのインストールに失敗してしまったのです.

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

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

    # find / -group GID -print

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

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

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

自信家の方は, このステップを省略しても構いません.

FreeBSD 2.2.5-RELEASE 以降の場合: 以下に詳しく述べられているように, 2.2.5-RELEASE 以降, ビルド(システムの構築)とインストールの行程を分離して行なうことが可能になりました. そのため, マルチユーザモードで新しいシステムのビルドを行ない, その後, シングルユーザモードに移行してから インストールを行なうことができます.

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

    # shutdown now

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

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

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

19.4.5. /usr/obj の削除

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

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

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

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

19.4.6. ソースの再構築と新しいシステムのインストール

19.4.6.1. 全バージョンに共通すること

まず, カレントディレクトリを /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 -DNOPROFILE=true target

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

    NOPROFILE=    true
    #    Avoid compiling profiled libraries

の行に対応します.

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

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

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

    # make target

19.4.6.2. 出力の保存

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

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

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

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

19.4.6.3. FreeBSD-2.2.2 と, それ以前のバージョン

/usr/src/Makefile には, システム全体を再構築しインストールを行なう world ターゲットが含まれています.

それを, 次のように使って下さい.

    # make world

19.4.6.4. FreeBSD-2.2.5 と, それ以降のバージョン

FreeBSD-2.2.5 から(実際には, -CURRENT ブランチで最初に作成され, 2.2.2 と 2.2.5 の間の時点で -STABLE に導入されたのですが), world ターゲットは buildworldinstallworld の二つに分割されました.

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

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

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

一方, world ターゲットも残されていますので, FreeBSD-2.2.2 の場合として示されている方法と同じように, このターゲットを利用することもできます. make world は, make buildworld に続けて make installworld を実行します.

Note: make buildworldmake installworld のコマンドを分けて実行する場合には, それぞれ同じ引数を make(1) に渡さなければなりません.

次のように実行したとすると,

    # make -DNOPROFILE=true buildworld

構築されたシステムは次のようにしてインストールする必要があります.

    # make -DNOPROFILE=true installworld

そうしないと, make buildworld の段階で 構築されていない, プロファイル版ライブラリのインストールを 試みることになります. (訳注: もちろん, それには失敗するのでエラーが発生します. )

19.4.6.5. -CURRENT と, それ以降

もし, -CURRENT を追跡しているなら, make コマンドに -j オプションを渡すことができます. このオプションにより, make は 同時に複数のプロセスを生成するようになります.

これは, 実際に複数の CPU を備えているマシンに対して 非常に有効に働きます. また, コンパイルプロセスの大部分は CPU の処理ではなく入出力の処理に費やされるため, 単一の CPU を持つマシンでも同じように有効です.

単一の CPU を持つ典型的なマシンでは, 次のように実行します.

    # make -j4 target

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

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

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

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

すべてが順調に進んでいたとしても, 一時間半から丸一日程度の時間がかかります.

一般的に言って, 200MHz の P6(訳注: Intel PentiumPro のこと) で 32MB 以上のメモリを搭載し, 標準的な SCSI ディスクドライブを利用していた とすると, make world の完了までに およそ一時間半の時間がかかります. この構成よりも性能が低ければ, それよりもさらに時間がかかるでしょう.

19.4.7. /etc の更新

システムの再構築は, いくつかのディレクトリ ( 特に, /etc, や /var/usr) において, 新規に導入されたり, 変更された設定ファイルによる ファイルの更新は行なわれません. これは, あなた自身の手や目, そして適切な diff(1) の使用をによって行なわなければなりません.

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

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

既存の /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 | /usr/bin/perl -lne \
    'opendir(D,$_);@f=readdir(D);rmdir if $#f == 1;closedir(D);'

これは深さ優先探索で各ディレクトリを走査し, 含まれるファイルの数が 2 個(スクリプト中の "1" は typo ではありません), すなわち "."".." ならば, そのディレクトリを削除します.

この段階の /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 ファイルと 新しい /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"`

19.4.8. /dev の更新

DEVFS: もし, DEVFS を利用しているなら, この作業はおそらく必要ないでしょう.

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

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

        # cp /var/tmp/root/dev/MAKEDEV /dev
  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
    適当な組み合わせは, 環境によって異なります.

19.4.9. /stand の更新

Note: この段階は, 完全な更新を行なう場合にだけ必要な内容を含んでいます. 悪影響はありませんので, 省略しても構いません.

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

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

1998 年 4 月 2 日以前のソースの場合: もし, 1998 年 4 月 2 日より古いソースコードを使っているか, Makefile のバージョンが 1.68 以降(FreeBSD-CURRENT および FreeBSD-3.X の場合), 1.48.2.21 以降(FreeBSD-2.2.X の場合)でなければ, 次のように NOSHARED=yes オプションを追加する必要があります.

    # make NOSHARED=yes all install

19.4.10. 新しいカーネルのコンパイルとインストール

新しいシステムにおけるアドバンテージを完全に得るために, カーネルの再コンパイルをすべきです. 再コンパイルは, ある種のメモリ構造が変更された時には必須です. その場合, ps(1)top(1) のようなプログラムは, カーネルとソースコードのバージョンが一致しないと 正常に動作しないでしょう.

新しい kernel をコンパイルするには, FreeBSD ハンドブックの指示にしたがってください. 過去に自分で設定したカーネルを構築している場合には, LINT コンフィグレーションファイルを注意深く調べて, 利用できる新しいオプションがあるかどうか確かめて下さい.

この文書の以前の版では, カーネルの再構築の前に再起動することを推奨していました. これは以下の点で誤りです.

これらの理由から, どんな場合においても, 再起動する前に新しいカーネルを再構築し, インストールすることが 最も良い手順になります.

新しいカーネルは, make world (あるいは make installworld) が完了した後で 構築しなければなりません. もし, そうしない場合には (おそらく, あなたはシステムを更新する前にカーネルが構築されることを 確認したいのでしょう) 問題が起こるかも知れません. それは, カーネルソースに対して config(8) コマンドが古いことが原因です.

その場合には, 新しいバージョンの config(8) でカーネルを構築することができます.

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

これは, いつもうまく行くとは限りませんので, 新しいをカーネルをコンパイルする前に make world (あるいは make installworld)を完了させることが推奨されています.

19.4.11. 再起動

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

    # fastboot

19.4.12. 作業の完了

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

さて, この時点で, 今までの間違った操作による小さな問題に 気付くことがあるかも知れません. たとえば, 私はかつて /etc/magic をアップグレードの途中で削除し, そのまま /etc にマージしてしまったことがあります. その結果, file コマンドは動作しなくなってしまったのです. すぐに思いついたのは, これを修復するには

    # cd /usr/src/usr.bin/file
    # make all install
だけで十分ではないか, ということでした.

19.4.13. 質問ですか?

Q: 変更が行なわれたら, その度にシステムの再構築が必要になるのでしょうか?
Q: signal 12(もしくは他のシグナル番号)のエラーがたくさん出て コンパイルが失敗します. 何が起こっているんでしょうか?
Q: 終了したら /usr/obj を削除しても かまいませんか?
Q: 構築を中断した場合, その構築を途中から再開することはできますか?
Q: あるマシンを マスタ として, 他の多くのマシンを (NFSで) アップグレードできますか?
Q: どのようにすれば make world を高速化できますか?

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

A: それは変更の性質によるので, なんとも言えません. 例えば, 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 週間の変更を取り込めば 幸せかもしれませんし, 変更のあった部分だけ再構築し, 依存関係を確かめたいと考えるかも知れません.

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

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

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

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

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

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

A: それはあなたが次の機会に, システムの再構築をどう行なうつもりなのかによります.

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

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

もし, このような危険を承知した上でシステムの再構築を行なう場合には, 次のように変数 NOCLEAN を定義して構築します.

    # make -DNOCLEAN world

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

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

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

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

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

これは, 前回の "make world" の作業をやり直しません.

次のメッセージ

    --------------------------------------------------------------
    Building everything..
    --------------------------------------------------------------
"make world" の出力にある場合には, 上のようにしてもほとんど悪影響が現れることはありません.

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

Q: あるマシンを マスタ として, 他の多くのマシンを (NFSで) アップグレードできますか?

A: すべてのコンパイル作業をあるマシンで行ない, 構築されたものを他のマシンにネットワークを経由で make install することができるかどうかは, よく FreeBSD メーリングリストで尋ねられます.

これはわたしが行った作業ではありませんので, 下に書かれている提案は, 他の人々から頂いたか, Makefile から推論したものです.

取るべき適切な方法については, 利用している FreeBSD のバージョンに依存します.

アップグレードしたマシンでは, この作業を行った後に /etc/dev の 更新を行わなくてはなりません.

2.1.7 とそれより古いものについて, Antonio Bemfica は 次に示すような方法を教えてくれました.

    Date: Thu, 20 Feb 1997 14:05:01 -0400 (AST)
    From: Antonio Bemfica <bemfica@militzer.me.tuns.ca>
    To: freebsd-questions@FreeBSD.org
    Message-ID: <Pine.BSI.3.94.970220135725.245C-100000@militzer.me.tuns.ca>
    
    Josef Karthauser は質問しました:
    
    > どなたかネットワークを通してマシンをアップグレードするよい方法は知りませんか
    
    まず, メインとなるマシンで make world などをします.
    そして次のように, リモートのマシンから / や /usr をマウントします:
    
    main_machine% mount remote_machine:/   /mnt
    main_machine% mount remote_machine:/usr /mnt/usr
    
    そして, /mnt をインストール先に指定して 'make install' とします:
    
    main_machine% make install DESTDIR=/mnt
    
    これをネットワーク上の他のマシンについても繰り返してください.  
    わたしの場合には, これでうまくいきました.
         
    Antonio

この仕組みは (わたしの知る限り) NFS サーバ上の /usr/src が書き込み可能である場合にのみ きちんと動作します. FreeBSD-2.1.7 とそれ以前では, この作業に install ターゲットを使います.

FreeBSD-2.1.7 と FreeBSD-2.2.0 の間で "reinstall" ターゲットが導入されました. 上にあげた FreeBSD-2.1.7 向けの方法に加え, "install" の代わりに "reinstall" を 使うことができます.

この方法では, NFS サーバ上の /usr/src ディレクトリへの書き込み権限は必要 ありません.

Makefile の 1.68 から 1.107 の間のバージョンには, このターゲットに関するバグがありました. それは NFS サーバへの書き込み権限が 必要になる というもので, このバグは FreeBSD-2.2.0 がリリースされる前に修正されました. この時期の -STABLE が動いている古いサーバでは, 問題になるかも知れません.

FreeBSD-2.2.5 以降のバージョンでは, "buildworld""installworld" ターゲットが利用できます. これらを使ってソースツリーを一つのマシンで構築し, /usr/src/usr/obj をリモートマシンで NFS マウントして, そこからインストールすることができます.

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

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

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

  • さらに高速化するには, これらのファイルシステムを "ccd" (連結ディスクドライバ) デバイスを 使って, 別々なディスク上に置いてください.

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

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

  • (もしあなたが十分に最近のバージョンの FreeBSD を使っているなら) 複数のプロセスを並列に実行させるため, make に -j<n> オプションを指定してください. これはプロセッサが単一か複数かによらず, どちらも同様に恩恵を得ることができます.

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

    Note: "noatime" が利用可能なのは, FreeBSD-2.2.0 以降です.

        # 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 自身が ファイルシステムでない場合には, 適切なマウントポイントを指すように, 上の例の名前を置き換えて下さい.