<?xml version="1.0" encoding="euc-jp"?>
<!DOCTYPE article PUBLIC "-//FreeBSD//DTD DocBook XML V4.5-Based Extension//EN"
	"../../../share/xml/freebsd45.dtd" [
<!ENTITY scratch.ap "<application>FreeBSD をゼロから設定する</application>">
]>

<!--
  $FreeBSD$
  Original revision: 1.11
-->

<article xmlns:xi="http://www.w3.org/2001/XInclude" lang='ja'>
  <articleinfo>
    <title>FreeBSD をゼロから設定するには</title>

    <author>
      <firstname>Jens</firstname>
      <surname>Schweikhardt</surname>
      <affiliation>
        <address><email>schweikh@FreeBSD.org</email></address>
      </affiliation>
    </author>
    <copyright>
      <year>2002</year>
      <year>2003</year>
      <year>2004</year>
      <holder>Jens Schweikhardt</holder>
    </copyright>

    <legalnotice id="trademarks" role="trademarks">
      &tm-attrib.freebsd;
      &tm-attrib.adobe;
      &tm-attrib.general;
    </legalnotice>

    <pubdate>$FreeBSD$</pubdate>

    <releaseinfo>$FreeBSD$</releaseinfo>
  </articleinfo>

    <abstract>
      <para>この記事は、「&scratch.ap; (FreeBSD From Scratch)」という、
        わたしの個人的な経験をまとめたものです。
        カスタマイズした &os; システムをソースからコンパイルし、
        さらに好みの ports のコンパイルして、
        あなたが望む構成のシステムの、
        完全に自動化されたインストールを実現します。
        <command>make world</command>
        がすばらしい考え方だとお思いの方にとって、
        「&scratch.ap;」は、まさに <command>make world</command> を
        <command>make evenmore</command> (さらにその先)
        へと広げるものになることでしょう。</para>
    </abstract>

  <sect1 id="introduction">
    <title>はじめに</title>

    <para>今までに <command>make world</command>
      を使ってシステムをアップグレードした経験はあるでしょうか?
      もしディスクに一つのシステムしか入れていない場合は問題です。
      <maketarget>installworld</maketarget> が途中で止まってしまったら、
      あなたのシステムは壊れたまま、もう起動しなくなってしまうかも知れません。
      あるいは、<maketarget>installworld</maketarget> が正常に終了しても、
      新しいカーネルは起動に失敗してしまうかも知れません。
      さて、そうなってしまったら、Fixit CD
      を取り出して半年前のバックアップを戻す、
      なんてはめになってしまうかも知れませんよね。</para>

    <para>わたしは、<quote>アップグレードの時はディスクを初期化する</quote>
      という方法がよいと考えています。パーティションではなくディスク全体のデータを
      消去することで、アップグレードの手順では無視されるような古いデータが
      残ってしまうことを防ぐことができます。ただ、
      パーティションを全部初期化するということは、
      ports/packages をすべて再コンパイル・再インストールしなければならず、
      設定ファイルも注意深く作成し直さなければならないということです。
      こういう作業を自動化したいと思いませんか?
      そう思う人は、この先を読み進めましょう。</para>
  </sect1>

  <sect1 id="why">
    <title>どうして「&scratch.ap;」(あるいは「~しない」)
      ことが必要なのか</title>

    <para>これはもっともな質問です。
      すでに <application>sysinstall</application> がありますし、
      カーネルとユーザランドツールをコンパイルする方法には、
      もっと有名な方法が他にもあるからです。</para>

    <para><application>sysinstall</application>
      の問題は、「何を、どこに、
      どうやってインストールするのか」が非常に限定されているという点です。</para>

    <itemizedlist>
      <listitem>
        <para><application>sysinstall</application>
          は通常、構築ずみの配布物セットと packages を
          (CD, DVD, FTP などの)
          別の場所からインストールする時に使われるものであり、
          <literal>make buildworld</literal>
          の結果をインストールできるようにはできていません。</para>
      </listitem>

      <listitem>
        <para>現在稼働中のシステム中にあるディレクトリに、
           新しいシステムをインストールすることはできません。</para>
      </listitem>

      <listitem>
        <para><application>Vinum</application>
          パーティションへのインストールはできません。</para>
      </listitem>

      <listitem>
        <para>構築ずみの packages はインストールできますが、
          ports を構築することはできません。</para>
      </listitem>

      <listitem>
        <para>スクリプトを使ったり、
          インストール後に変更するための処理を自由に入れることは困難です。</para>
      </listitem>

      <listitem>
        <para>最後の大きな理由として、<application>sysinstall</application>
          が、公式にもう積極的に使わないプログラムと考えられている、
          ということがあげられます。</para>
      </listitem>
    </itemizedlist>

    <para>システム全体を構築してインストールする方法は、
      <ulink url="http://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/makeworld.html"
        >ハンドブック</ulink>にある方法が有名です。
      これはデフォルトで既存のシステムを置き換えるもので、
      カーネルとモジュールだけが保存され、
      システムバイナリ、ヘッダ、その他の多くのファイルは上書きされます。
      使われなくなった古いファイルはそのまま残り、
      動作に問題が出ることもあります。
      何らかの理由でアップグレードに失敗すると、
      システムを元の状態に戻することは不可能か、できても非常に困難です。</para>

    <para>「&scratch.ap;」方法は、これらの問題をすべて解決できます。
      考え方は単純です。
      稼働中のシステムを使って空のディレクトリにシステムをインストールします。
      その時、その新しいシステムのディレクトリツリーには、
      新しいパーティションを適切にマウントしておaきます。
      数多くある設定ファイルは、コピーできるものは適切な場所にコピーし、
      それができないものには &man.mergemaster.8; を使います。
      新しいシステムに対するインストール後の設定は、
      古いシステムを動作させながら、新しいシステムに対して chroot して
      自由に行なうことができます。具体的には、
      シェルスクリプト、もしくは <command>make</command>
      の実行で構成される、次の 3 段階でこれらを実現します。</para>

    <orderedlist>
      <listitem>
        <para><filename>stage_1.sh</filename>:
          新しい起動可能なシステムを空のディレクトリ以下に作成し、
          必要なファイルをマージ、もしくはコピーします。
          そして、新しいシステムを起動します。
        </para>
      </listitem>

      <listitem>
        <para><filename>stage_2.sh</filename>:
          必要な ports をインストールします。</para>
      </listitem>

      <listitem>
        <para><filename>stage_3.mk</filename>:
          ひとつ前の段階でインストールしたソフトウェアの、
          インストール後の設定を行ないます。</para>
      </listitem>
    </orderedlist>

    <para>新しいシステムを構築するために「&scratch.ap;」方法を使い、
      それが数週間、満足する程度に動作していることを確認したら、
      もう一度それを使って、大元のシステムを再インストールすることができます。
      これからはいつでも好きな時にシステムを更新して、
      初期化・再インストールしたパーティションに切り替えるだけでよくなるわけです。</para>

    <para><ulink url="http://www.linuxfromscratch.org/">Linux From Scratch</ulink>
      (もしくは省略して LFS) について耳にしたり、試された方がいらっしゃるかも知れません。
      LFS も同じように、稼働中のシステムを使ってシステムをゼロから構築し、
      空のパーティションにインストールする方法が書かれています。
      LFS が話題の中心としているのは、(カーネル、コンパイラ、デバイス、
      シェル、端末データベースなどの) 各システムコンポーネントの役割と、
      それらのインストールの詳細を見せることのようです。
      この「&scratch.ap;」では、そのような詳細には触れません。
      わたしの目的は、インストールを終わりまで自動化することであり、
      システム構築時の泥くさい過程を全部説明することではありません。
      &os; をそのようなレベルで掘り下げてみたい人は、
      <filename>/usr/src/Makefile</filename> を読んで、
      <command>make buildworld</command>
      の動作を追いかけるところから始めましょう。</para>

    <para>また、「&scratch.ap;」方法にも、
      次のような欠点があることを心に留めておいてください。</para>

      <!-- XXX: A nice idea would be to write stage_2.sh using a jail
           that runs into the newly installed world from stage_1.  Having
           properly set up a network address as the jail's primary IP
           address, it might even be possible to build ports in a chroot
           without uninstalling anything from the 'host' system.  But
           keep in mind that even jails run on the 'host' kernel. -->

    <itemizedlist>
      <listitem>
        <para>第 2 段階で ports をコンパイルしている間、
          システムは通常の用途に使用することができません。
          もしプロダクションサーバを運用しているなら、
          第 2 段階でダウンタイムが発生することを考慮に入れなければなりません。
          <filename>stage_2.conf.default</filename> の ports のコンパイルには、
          AMD1800+、10,000rpm SCSI、1GB の RAM を搭載したシステムで、
          約 4 時間かかります。ports の代わりに package
          をインストールすれば、この時間を 10 分程度にまで大幅に短縮することも可能です。</para>
      </listitem>
    </itemizedlist>
  </sect1>

  <sect1 id="prerequisites">
    <title>前提とする環境</title>

    <para>「&scratch.ap;」方法を実行するには、
      次のものが必要です。</para>

    <itemizedlist>
      <listitem>
        <para>ソースと ports ツリーを含む、稼働中の &os; システム</para>
      </listitem>

      <listitem>
        <para>新しいシステムをインストールするための、
          最低 1 個の未使用パーティション</para>
      </listitem>

      <listitem>
        <para>&man.mergemaster.8; を実行した経験。もしくは、
          それを実行する勇気。</para>
      </listitem>

      <listitem>
        <para>インターネット接続環境がない、あるいは遅い場合には、
          インストールしたい ports の配布ファイル</para>
      </listitem>

      <listitem>
        <para>Bourne シェル (&man.sh.1;)
          を使ってシェルスクリプトを作成するための基礎知識</para>
      </listitem>

      <listitem>
        <para>新しいシステムを起動する方法を、
          対話的あるいは設定ファイルを使ってブートローダに
          教えることができること</para>
      </listitem>
    </itemizedlist>
  </sect1>

  <sect1 id="stage1">
    <title>第 1 段階: システムのインストール</title>

    <para>この文書の初版では、第 1 段階にひとつのシェルスクリプトを使っていました。
      カスタマイズはすべて、そのスクリプトを編集する必要があったのですが、
      利用者からの意見を参考にして、スクリプトのコードとデータを分離することにしました。
      そのため新しいスクリプトでは、コードスクリプトを変更せずに、
      複数の異なるシステムに異なる構成のデータを置くことが可能になりました。</para>

    <para>第 1 段階のコードスクリプトは
      <filename>stage_1.sh</filename> であり、次のように 1
      個の引数をつけて実行すると</para>

    <informalexample>
      <screen>&prompt.root; <userinput>./stage_1.sh <replaceable>default</replaceable></userinput></screen>
    </informalexample>

    <para>設定ファイルとして
      <filename>stage_1.conf.default</filename> を読み込み、
      ログファイルとして
      <filename>stage_1.log.default</filename> に書き込みます。</para>

    <para>文末にわたしが使っている <filename>stage_1.conf.default</filename>
      が添付してあります。
      あなたが考える <quote>完璧なシステム</quote> に合わせて、
      各設定をカスタマイズしてください。あなたが変更しそうな設定には、
      詳細なコメントを追加してあります。設定スクリプトでは、
      <command>create_file_systems</command>,
      <command>create_etc_fstab</command>, <command>copy_files</command>,
      <command>all_remaining_customization</command> という、
      4 個のシェル関数を提供しなければなりません (これは、
      <filename>stage_1.sh</filename> から呼ばれる順に書いてあります)。</para>

    <para>考慮すべき点は、以下のとおりです。</para>

    <itemizedlist>
      <listitem>
        <para>パーティションの配置</para>

        <para>わたしは、システム全体を一つの大きな
          パーティションに入れるという考え方が好きではないので、
          普通は
          <filename>/</filename>、
          <filename>/usr</filename>、
          <filename>/var</filename> の
          パーティションを分割し、<filename>/tmp</filename> を
          <filename>/var/tmp</filename> のシンボリックリンクにしています。
          また、<filename>/home</filename> (ユーザのホームディレクトリ)、
          <filename>/home/ncvs</filename> (&os; CVS リポジトリの複製),
          <filename>/usr/ports</filename> (ports ツリー),
          <filename>/src</filename> (チェックアウトした src ツリー)、
          <filename>/share</filename> (news スプールなど、バックアップする必要がない、
          その他の共有データ) といったファイルシステムを、
          古いシステムと新しいシステムで共有しています。</para>
      </listitem>

      <listitem>
        <para>その他の項目</para>

        <para>これは、新しいシステムの起動後にすぐに実行したいことや、
          第 2 段階の前に実行したい内容のことです。
          なぜ第 1 段階で単純に新しいシステムに chroot してお気に入りの
          ports をインストールしないのかというと、理論的にも、
          実際の手順にも卵鶏問題があるからです。第 1 段階では、
          古いカーネルが動作していますが、chroot 環境には、
          新しいバイナリとヘッダが使われています。もしその新しいバイナリが、
          古いカーネルには存在しない新しいシステムコールを使っていたら、
          <literal>SIGSYS, Bad system call</literal>
          というエラーが出て停止してしまうでしょう。わたしは
          <filename role="package">lang/perl5</filename>
          を構築する時にも問題が発生することを確認しています。
        </para>
      </listitem>
    </itemizedlist>

    <para><filename>stage_1.sh</filename> を実行する前に、
      <command>make installworld installkernel</command>
      を実行するために通常行なう作業を完了させておいてください。
      これらは、たとえば次のようなものです。</para>

    <itemizedlist>
      <listitem>
        <para>カーネルコンフィグファイルの設定</para>
      </listitem>

      <listitem>
        <para><command>make buildworld</command>
          を正常終了させておくこと</para>
      </listitem>

      <listitem>
        <para><command>make buildkernel
            KERNCONF=<replaceable>whatever</replaceable></command>
          を正常終了させておくこと</para>
      </listitem>
    </itemizedlist>

    <para>初めて <filename>stage_1.sh</filename> を実行した場合は、
      稼働中のシステムから新しいシステムへとコピーされる設定ファイルは
      <filename>/usr/src</filename> のものと比べると古いので、
      <command>mergemaster</command> がどうするかを聞いてきます。
      おすすめは、ここで変更点を統合しておくことです。
      もし、何度も質問に答えるのが面倒であれば、
      <emphasis>稼働中の</emphasis>システムのファイルを更新しておきましょう
      (ただしこれは、そうできればの話です。
      <literal>-STABLE</literal> のシステムを実行していて、
      <literal>-CURRENT</literal> を構築する、
      もしくはその逆のようなケースでは、そうしてはいけません)。
      次に <command>mergemaster</command> を実行した時、
      RCS バージョン ID が <filename>/usr/src</filename>
      にあるファイルと一致しているものは、処理が飛ばされるようになります。</para>

    <para><filename>stage_1.sh</filename> スクリプトは
      <command>set -e</command> が指定されており、
      最初のコマンドが失敗 (終了コードが 0 以外) すると停止します。
      そのため、エラーを見逃してしまうということはないでしょう。
      これは、タイプミスなどで未定義の変数を使った場合にもエラーになります。
      次に進む前に、<filename>stage_1.conf.default</filename>
      にあるエラーを全部修正しておいてください。</para>

    <para><filename>stage_1.sh</filename> では
      <command>mergemaster</command> が実行されます。
      統合作業をしなければならないファイルが一つもない状態でも、
      実行の終わりに次のメッセージが表示されます。</para>

    <screen>*** Comparison complete

Do you wish to delete what is left of /var/tmp/temproot.stage1? [no] <userinput>no</userinput></screen>

    <para><literal>no</literal> と答えるか、
      単に <keycap>Enter</keycap> を押してください。
      なぜかと言うと、<command>mergemaster</command>
      は <filename>/var/tmp/temproot.stage1</filename>
      にサイズが 0 のファイルをいくつか残すからです。
      これは、後で新しいシステムに (存在しなければ) コピーされます。</para>

    <para>この後、インストールされたファイルのリストがページャ
      (デフォルトでは &man.more.1; です。&man.less.1; を使うこともできます)
      に表示されます。</para>

<screen>*** You chose the automatic install option for files that did not
    exist on your system.  The following were installed for you:
      /newroot/etc/defaults/rc.conf
      ...
      /newroot/COPYRIGHT

(END)</screen>

    <para><keycap>q</keycap> を入力してページャを終了します。
      すると <filename>login.conf</filename> に関して、次のように表示されます。</para>

    <screen>*** You installed a login.conf file, so make sure that you run
    '/usr/bin/cap_mkdb /newroot/etc/login.conf'
    to rebuild your login.conf database

    Would you like to run it now? y or n [n]</screen>

    <para>これに対する答えはどちらでも構いません。
      どう答えても、スクリプトから &man.cap.mkdb.1; が実行されます。</para>

    <para>次に示すのは、筆者の使っている <filename>stage_1.conf.default</filename>
      ですが、たくさんの部分を書き換える必要がありますので注意してください。
      どこを書き換えればよいのかについては、コメントを読めば十分理解できると思います。</para>

    <warning>
      <para>&man.newfs.8; コマンドには注意してください。
        マウントずみのパーティションに新しいファイルシステムを作成することはできないものの、
        このスクリプトはマウントされていない
        <filename>/dev/da0s1a</filename>, <filename>/dev/da0s1e</filename>,
        <filename>/dev/da2s1e</filename> をすべて削除します。
        ひとつ間違えれば、あなたの環境を破壊してしまう可能性がありますので、
        デバイス名の変更は注意深く行なってください。</para>
    </warning>

<programlisting>
<xi:include href="../../../en_US.ISO8859-1/articles/fbsd-from-scratch/stage_1.conf.default" parse="text"/>
</programlisting>

    <para>ダウンロード: <ulink
        url="../../../en_US.ISO8859-1/articles/fbsd-from-scratch/stage_1.conf.default"><filename>stage_1.conf.default</filename>
      </ulink>.</para>

    <para>このスクリプトを実行すると、
      起動した時に次のような状態になっているシステムがインストールされます。</para>

    <itemizedlist>
      <listitem>
        <para>稼働中のシステムと同じユーザとグループ</para>
      </listitem>
      <listitem>
        <para>Ethernet と PPP を経由した、
          ファイアウォールありのインターネット接続環境</para>
      </listitem>
      <listitem>
        <para>正しいタイムゾーンと NTP 設定</para>
      </listitem>
      <listitem>
        <para><filename>/etc/ttys</filename> や
        <command>inetd</command> など、その他の細かな設定。</para>
      </listitem>
    </itemizedlist>

    <para>他の部分に対する設定は、第 2 段階が終わるまで動作しません。
      たとえば、プリンタや X11 の設定ファイルもコピーされますが、
      プリンタは &postscript; ユーティリティなど、
      ベースシステムに含まれないアプリケーションを使うことが多いでしょう。
      X11 はサーバ、ライブラリ、プログラムをコンパイルしないと動作しません。</para>
  </sect1>

  <sect1 id="stage2">
    <title>第 2 段階: ports のインストール</title>

    <note>
      <para>この段階で ports をコンパイルするのではなく、
        (コンパイルずみの) packages をインストールすることもできます。
        その場合、<filename>stage_2.sh</filename> は
        単に <command>pkg_add</command> コマンドを羅列するだけになるでしょう。
        読者のみなさんにとって、そういうスクリプトを書くのは難しくないと思いますので、
        ここではもっと柔軟で、ports
        を使った伝統的な方法について考えることにします。</para>
    </note>

    <para>次に紹介する <filename>stage_2.sh</filename> スクリプトは、
      わたしが好みの ports をインストールするために使ったものです。
      これは何度でも実行でき、インストールずみの ports があれば、
      飛ばして処理されます。スクリプトは <emphasis>実行せず、実行される内容だけ
        を表示する (dryrun)</emphasis> オプション (<option>-n</option>)
      があります。実行時には <filename>stage_1.sh</filename> と同様、
      設定スクリプトを示すためのひとつの引数を指定します。</para>

    <informalexample>
      <screen>&prompt.root; <userinput>./stage_2.sh <replaceable>default</replaceable></userinput></screen>
    </informalexample>

    <para>これは、ports のリストを
      <filename>stage_2.conf.default</filename> というファイルから読み込みます。</para>

    <para>ports リストは、空白で区切られた 2 個以上のキーワードからなっています。
      カテゴリ、port 名に始まり、オプションとして
      port をコンパイルしてインストールするためのコマンド
      (デフォルトは <command>make install BATCH=yes &lt; /dev/null</command>) が続きます。
      空白行と # から始まる行は無視されます。
      おそらく多くの場合に考えなければならないのは、カテゴリ名と port 名だけでしょう。
      ports によっては、たとえば次のように
      <command>make</command> 変数を使って微調整することができます。</para>

    <programlisting>www mozilla make WITHOUT_MAILNEWS=yes WITHOUT_CHATZILLA=yes install</programlisting>

    <para>実際には任意のシェルコマンドを指定できますので、
      <command>make</command> を使う以外にも応用は可能です。</para>

    <programlisting>java linux-sun-jdk13 yes | make install
news inn-stable CONFIGURE_ARGS="--enable-uucp-rnews --enable-setgid-inews" make install</programlisting>

    <para><filename role="package">news/inn-stable</filename> の行は、
      <literal>CONFIGURE_ARGS</literal> という シェル変数を定義した例です。
      この port の <filename>Makefile</filename> は、
      この指定した値を変数の初期値として、その他の必須の引数と一緒に使います。
      これと</para>

    <programlisting>news inn-stable make CONFIGURE_ARGS="--enable-uucp-rnews --enable-setgid-inews" install</programlisting>

    <para>のようにして
      <application>make</application> 変数をコマンドラインに設定した場合との違いは、
      こちらの場合に変数そのものを完全に上書きしてしまうという点です。
      どの方法を使えばいいのかについては、各 port によります。</para>

    <para>インストールしたい ports が、
      対話的インストールを使っていないことを確認してください。
      ports は、あなたが標準入力に明示的に指定したもの以外、
      標準入力を読み込む動作をしてはいけません。
      もし ports がそのように作られていると、ports はヒアドキュメントにある
      ports リストの次の行を読み込んで混乱してしまいます。
      <filename>stage_2.sh</filename> を実行した時、
      ある port が飛ばされたり、動作が止まってしまうようなことがあれば、
      おそらくこれが原因でしょう。</para>

    <para>次に示すのは <filename>stage_2.conf.default</filename> です。
      これは、インストールされる port それぞれに対して
      <filename>LOGDIR/category+port</filename>
      という名前のログファイルが作成されます。</para>

<programlisting>
<xi:include href="../../../en_US.ISO8859-1/articles/fbsd-from-scratch/stage_2.conf.default" parse="text"/>
</programlisting>

     <para>ダウンロード: <ulink
        url="../../../en_US.ISO8859-1/articles/fbsd-from-scratch/stage_2.conf.default"><filename>stage_2.conf.default</filename></ulink>.</para>
  </sect1>

  <sect1 id="stage3">
    <title>第 3 段階</title>

    <para>第 2 段階で、好みの ports がインストールされましたが、
      ports には、設定を必要とするものがあります。
      第 3 段階は、インストール後の設定を行なう段階です。
      <filename>stage_2.sh</filename> の最後にこの段階を統合することもできたのですが、
      わたしは port をインストールすることと初期設定を変更することが異なる工程であると考えたため、
      独立した段階としています。</para>

    <para>第 3 段階は、<filename>Makefile</filename> として実装しています。
      これは、次のように実行することで、設定対象を簡単に選ぶことができるからです。</para>

    <informalexample>
      <screen>&prompt.root; <userinput>make -f stage_3.mk <replaceable>target</replaceable></userinput></screen>
    </informalexample>

    <para><filename>stage_2.sh</filename> の段階で、
      <filename>stage_3.mk</filename> を共有パーティションに置くか、
      新しいシステムのどこかにコピーするなどして、
      新しいシステムが起動した時に
      <filename>stage_3.mk</filename> が使えるようにしておきましょう。</para>
  </sect1>

  <sect1 id="limitations">
    <title>制限事項</title>

    <para>対話的で、かつ <command>make BATCH=YES install</command>
      でのインストールに対応していない port
      の自動インストールは難しいかも知れません。
      対話的にインストールする ports には、ライセンス条項の同意を尋ねられた時に
      <literal>yes</literal> と入力するだけのものがいくつかあります。
      そのように入力が標準入力から読みとられる場合は、
      適切な回答をインストールコマンド (通常は <command>make
        install</command>) にパイプで渡すことができます
      (わたしが <filename>stage_2.conf.default</filename> の
      <filename role="package">java/linux-sun-jdk14</filename>
      でとった方法がそうです)。</para>

    <para>しかしこの方法は、たとえば <filename
        role="package">editors/staroffice52</filename> の場合にはうまく動きません。
      これは X11 が実行されていることを要求するからです。
      インストール手順には多くのクリックや文字入力が必要なので、
      他の ports のように自動化することはできません。
      わたしは、次のようにして問題を回避しました。
      最初に古いシステムで staroffice の package を作成し、</para>

    <informalexample>
      <screen>&prompt.root; <userinput>cd /usr/ports/editors/staroffice52</userinput>
&prompt.root; <userinput>make package</userinput>
===>  Building package for staroffice-5.2_1
Creating package /usr/ports/editors/staroffice52/staroffice-5.2_1.tbz
Registering depends:.
Creating bzip'd tar ball in '/usr/ports/editors/staroffice52/staroffice-5.2_1.tbz'</screen>
    </informalexample>

    <para>その後、第 2 段階で次のようにしたわけです。</para>

    <informalexample>
      <screen>&prompt.root; <userinput>pkg_add /usr/ports/editors/staroffice52/staroffice-5.2_1.tbz</userinput></screen>
    </informalexample>

    <para>その他に、設定ファイルのアップグレード問題に気をつける必要があります。
      一般的に、設定ファイルの書式や内容がいつ変更されるかを知ることはできません。
      新しいグループが <filename>/etc/group</filename>
      に追加されるかも知れませんし、<filename>/etc/passwd</filename>
      に新しいフィールドが追加されるかも知れません。
      このような例は、実際に過去にありました。
      単純に古いシステムから新しいシステムに設定ファイルをコピーするだけで
      ほとんどの場合は十分なのですが、時には不都合な場合もあります。
      古いファイルを上書きする方法でシステムをアップグレードしたら、
      ローカルにある設定ファイルに新しく追加されたかも知れない項目を統合する目的で
      <command>mergemaster</command> を使うと思います。
      しかし残念なことに、<command>mergemaster</command>
      はベースシステムに存在するファイルだけで、インストールした
      ports については何も処理を行なってくれません。
      サードパーティ製ソフトウェアには、
      リリースのたびに設定ファイルのフォーマットが変更され、
      わたしをイライラさせるようなものもあります。
      このような予告なしの変更を検出するために、
      わたしは変更した設定ファイルを <filename>stage_3.mk</filename>
      と同じディレクトリにコピーしておき、
      <application>make</application> ルールを使って結果を比較しています。
      たとえば、<application>apache</application> の
      <filename>httpd.conf</filename> であれば、次のような
      <command>config_apache</command> というターゲットを用意しておきます。</para>

<programlisting>
@if ! cmp -s /usr/local/etc/apache2/httpd.conf httpd.conf; then \
    echo "ATTENTION: the httpd.conf has changed. Please examine if"; \
    echo "the modifications are still correct. Here is the diff:"; \
    diff -u /usr/local/etc/apache2/httpd.conf httpd.conf; \
fi
</programlisting>

    <para>差分が無害なものであると確認できたら、
       <command>cp /usr/local/etc/apache2/httpd.conf
        httpd.conf</command> を実行するわけです。</para>

    <para>わたしは
      <literal>5-CURRENT</literal> から <literal>5-CURRENT</literal>
      に更新するために
      「&scratch.ap;」方法を数回使いましたが、
      <literal>4-STABLE</literal> と <literal>5-CURRENT</literal>
      の間で更新を行なった経験はありません。
      異なるメジャーリリース番号の間は、非常の多数の変更が行なわれているため、
      更新作業はもっと複雑なものになると思います。
      (試したわけではないのですが)
      <literal>4-STABLE</literal> から <literal>4-STABLE</literal>
      への更新であれば、「&scratch.ap;」方法は問題なく動作するはずです。
      <literal>4-STABLE</literal> のユーザは、次の点を考慮してください。</para>

    <note>
      <para>デバイスファイルシステム &man.devfs.5; を使ってなければ、
	<command>all_remaining_customization</command> の中で
        &man.MAKEDEV.8; を使い、
	ハードウェア用のデバイスファイルを作成するとよいでしょう。</para>
    </note>
  </sect1>

  <sect1 id="files">
    <title>ファイル</title>

    <para>ここでは、すでに説明した設定ファイルの他に必要な、
      3 個のファイルを示します。</para>

    <para>これは <ulink
        url="../../../en_US.ISO8859-1/articles/fbsd-from-scratch/stage_1.sh"><filename>stage_1.sh</filename></ulink>
      スクリプトです。内容を変更する必要はないでしょう。</para>

<programlisting>
<xi:include href="../../../en_US.ISO8859-1/articles/fbsd-from-scratch/stage_1.sh" parse="text"/>
</programlisting>

    <para>ダウンロード: <ulink
        url="../../../en_US.ISO8859-1/articles/fbsd-from-scratch/stage_1.sh"><filename>stage_1.sh</filename></ulink>.</para>

    <para>これは <ulink
        url="../../../en_US.ISO8859-1/articles/fbsd-from-scratch/stage_2.sh"><filename>stage_2.sh</filename></ulink>
      スクリプトです。最初の部分にある変数を変更しましょう。</para>

<programlisting>
<xi:include href="../../../en_US.ISO8859-1/articles/fbsd-from-scratch/stage_2.sh" parse="text"/>
</programlisting>

    <para>ダウンロード: <ulink
        url="../../../en_US.ISO8859-1/articles/fbsd-from-scratch/stage_2.sh"><filename>stage_2.sh</filename></ulink>.</para>

    <para>これは、わたしが使っている <ulink
        url="../../../en_US.ISO8859-1/articles/fbsd-from-scratch/stage_3.mk"><filename>stage_3.mk</filename></ulink> です。
      設定を自動的におこなうための手順を、ここに入れます。</para>

<programlisting>
<xi:include href="../../../en_US.ISO8859-1/articles/fbsd-from-scratch/stage_3.mk" parse="text"/>
</programlisting>

    <para>ダウンロード: <ulink
        url="../../../en_US.ISO8859-1/articles/fbsd-from-scratch/stage_3.mk"><filename>stage_3.mk</filename></ulink>.</para>
  </sect1>
</article>