この節で説明するアプローチはすべてのパッケージには適用されませんが、異機種システム混在環境にインストールする場合にパフォーマンスを向上できます。このアプローチは、Solaris OS の一部として提供されるパッケージ (バンドル版のパッケージ) にはほとんど適用されませんが、アンバンドルのパッケージでは従来とは異なるパッケージ化を実行できます。
再配置可能パッケージを奨励する理由は、次の要件をサポートするためです。
パッケージを追加または削除しても、インストールされたソフトウェア製品の既存の動作は変わりません。
アンバンドルのパッケージは、新しいパッケージが既存の製品と干渉しないことを保証できるように、/opt の下に配置するようにしてください。
有効な複合パッケージを構築する場合、次の 2 つの規則に従います。
パッケージオブジェクトの大部分が配置される場所に基づいてベースディレクトリを確立します。
パッケージオブジェクトがベースディレクトリ以外の共通ディレクトリ (例: /etc) に配置される場合、prototype ファイルで絶対パス名として指定します。
つまり、「再配置可能」とはオブジェクトを任意の場所にインストールして実行できることを意味するため、ブート時に init で実行される起動スクリプトは再配置可能と見なすことができません。提供されるパッケージで相対パスとして /etc/passwd を指定することに問題はありませんが、配置できる場所は 1 つしかありません。
複合パッケージを構築する場合、インストールされた既存のソフトウェアに干渉しないように絶対パスを処理する必要があります。すべて /opt に含まれるパッケージでは、既存のファイルが存在しないためこの問題を回避できます。/etc のファイルがパッケージに含まれる場合、絶対パス名が相対パス名から予測されるのと同様に機能することを保証する必要があります。次の 2 つの例を考えてみましょう。
エントリがテーブルに追加されるか、オブジェクトがほかのプログラムまたはパッケージによって変更される可能性が高い新しいテーブルです。
オブジェクトを、build、awk、または sed クラスに属するファイルタイプ e として定義します。この作業を実行するスクリプトは、自身を追加するのと同程度効率的に自身を削除する必要があります。
新しいソリッドステートのハードディスクをサポートするには、エントリを /etc/vfstab に追加する必要があります。
pkgmap ファイルのエントリは次のようになります。
| 1 e sed /etc/vfstab ? ? ? | 
request スクリプトは、パッケージで /etc/vfstab を変更するかどうかをオペレータに確認します。オペレータが "no" と答えると、このジョブを手動で実行する方法が表示され、次の処理が実行されます。
| echo "CLASSES=none" >> $1 | 
オペレータが "yes" と答えると、次の処理が実行されます。
| echo "CLASSES=none sed" >> $1 | 
これによって、必要な変更を行うクラスアクションスクリプトが起動されます。sed クラスは、パッケージファイル /etc/vfstab が、ターゲットシステム上の同じ名前のファイルに対するインストールおよび削除の両方の処理を含む sed プログラムであることを意味します。
オブジェクトはまったく新しいファイルで、後から編集される可能性は高くありません。または、別のパッケージが所有するファイルを置き換えます。
パッケージオブジェクトをファイルタイプ f として定義して、変更を取り消すことができるクラスアクションスクリプトを使用してインストールします。
ソリッドステートのハードディスクをサポートするために必要な情報を提供するには、/etc に /etc/shdisk.conf という名前の新しいファイルが必要です。pkgmap ファイルのエントリは、次のようになります。
| . . . 1 f newetc /etc/shdisk.conf . . . | 
クラスアクションスクリプト i.newetc は、/etc に配置する必要があるファイルのインストールに使用されます。このスクリプトは、所定の場所に別のファイルが存在するかどうかを確認します。存在しない場合は新しいファイルをコピーするだけです。所定の場所にファイルが存在する場合、そのファイルをバックアップしてから新しいファイルをインストールします。スクリプト r.newetc は、必要に応じてこれらのファイルを削除して、元のファイルを復元します。インストールスクリプトの重要な部分を次に示します。
| # i.newetc
while read src dst; do
	  if [ -f $dst ]; then
	    dstfile=`basename $dst`
	    cp $dst $PKGSAV/$dstfile
	  fi
	  cp $src $dst
done
 
if [ "${1}" = "ENDOFCLASS" ]; then
	  cd $PKGSAV
	  tar cf SAVE.newetc .
	  $INST_DATADIR/$PKG/install/squish SAVE.newetc
fi | 
このスクリプトでは、PKGSAV 環境変数を使用して置き換えるファイルのバックアップを格納しています。引数 ENDOFCLASS がスクリプトに渡された場合、これらがこのクラスの最後のエントリであることをスクリプトに通知するのは pkgadd コマンドです。この時点で、パッケージのインストールディレクトリに格納された非公開の圧縮プログラムを使用して、保存されたファイルがアーカイブおよび圧縮されます。
パッケージの更新時には PKGSAV 環境変数の使用は信頼性がありませんが、(たとえばパッチによって) パッケージが更新されない場合、バックアップファイルはセキュリティー保護されています。次の削除スクリプトには、旧バージョンの pkgrm コマンドがスクリプトに PKGSAV 環境変数への正しいパスを渡さないという別の問題に対応するコードが含まれています。
削除スクリプトは次のようになります。
| # r.newetc
 
# make sure we have the correct PKGSAV
if [ -d $PKG_INSTALL_ROOT$PKGSAV ]; then
	  PKGSAV="$PKG_INSTALL_ROOT$PKGSAV"
fi
 
# find the unsquish program
UNSQUISH_CMD=`dirname $0`/unsquish
 
while read file; do
	  rm $file
done
 
if [ "${1}" = ENDOFCLASS ]; then
	  if [ -f $PKGSAV/SAVE.newetc.sq ]; then
	     $UNSQUISH_CMD $PKGSAV/SAVE.newetc
	  fi
 
	  if [ -f $PKGSAV/SAVE.newetc ]; then
	     targetdir=dirname $file	# get the right directory
	     cd $targetdir
		    tar xf $PKGSAV/SAVE.newetc
		    rm $PKGSAV/SAVE.newetc
	  fi
fi | 
このスクリプトでは、パッケージデータベースのインストールディレクトリの非公開アンインストールアルゴリズム (unsquish) が使用されます。これはインストール時に pkgadd コマンドによって自動的に実行されます。pkgadd コマンドによって明確にインストール専用として認識されないスクリプトはすべて、pkgrm コマンドで使用するためにこのディレクトリに残されます。このディレクトリの場所を知ることはできませんが、このディレクトリが平坦で、パッケージの適切な情報ファイルおよびインストールスクリプトがすべて含まれていることは信頼できます。このスクリプトでは、 unsquish プログラムが含まれるディレクトリからクラスアクションスクリプトが実行されることが保証されていることに基づいてディレクトリを検索します。
また、このスクリプトでは、ターゲットディレクトリが /etc だけであるとは仮定していません。実際には /export/root/client2/etc である場合もあります。正しいディレクトリは、2 通りの方法のいずれかで構成できます。
${PKG_INSTALL_ROOT}/etc 構成を使用する方法
pkgadd コマンドで渡されるファイルのディレクトリ名を取得する方法 (このスクリプトで実行)
パッケージ内の絶対オブジェクトごとにこのアプローチを使用することで、現在の望ましい動作が変わらないか、少なくとも回復可能であることを保証できます。
次に示すのは、複合パッケージに対して pkginfo ファイルと pkgmap ファイルを使用する例です。
| PKG=SUNWstuf NAME=software stuff ARCH=sparc VERSION=1.0.0,REV=1.0.5 CATEGORY=application DESC=a set of utilities that do stuff BASEDIR=/opt VENDOR=Sun Microsystems, Inc. HOTLINE=Please contact your local service provider EMAIL= MAXINST=1000 CLASSES=none daemon PSTAMP=hubert990707141632 | 
| : 1 1758 1 d none SUNWstuf/EZstuf 0775 root bin 1 f none SUNWstuf/EZstuf/dirdel 0555 bin bin 40 773 751310229 1 f none SUNWstuf/EZstuf/usrdel 0555 bin bin 40 773 751310229 1 f none SUNWstuf/EZstuf/filedel 0555 bin bin 40 773 751310229 1 d none SUNWstuf/HRDstuf 0775 root bin 1 f none SUNWstuf/HRDstuf/mksmart 0555 bin bin 40 773 751310229 1 f none SUNWstuf/HRDstuf/mktall 0555 bin bin 40 773 751310229 1 f none SUNWstuf/HRDstuf/mkcute 0555 bin bin 40 773 751310229 1 f none SUNWstuf/HRDstuf/mkeasy 0555 bin bin 40 773 751310229 1 d none /etc ? ? ? 1 d none /etc/rc2.d ? ? ? 1 e daemon /etc/rc2.d/S70dostuf 0744 root sys 450 223443 1 i i.daemon 509 39560 752978103 1 i pkginfo 348 28411 760740163 1 i postinstall 323 26475 751309908 1 i postremove 402 33179 751309945 1 i preinstall 321 26254 751310019 1 i preremove 320 26114 751309865 1 i r.daemon 320 24573 742152591 | 
S70dostuf は daemon クラスに属しますが、これにつながるディレクトリ (インストール時に配置済み) は none クラスに属します。ディレクトリがこのパッケージに固有の場合でも、none クラスのままにしてください。この理由は、最初にディレクトリを作成して、最後に削除する必要がありますが、これは none クラスの場合も常に該当するためです。pkgadd コマンドによってディレクトリが作成されます。このディレクトリは、パッケージからコピーされたり、作成されるクラスアクションスクリプトに渡されたりすることはありません。その代わり、pkgadd コマンドで作成してからインストールクラスアクションスクリプトが呼び出され、削除クラスアクションスクリプトの完了後に、pkgrm コマンドによってディレクトリが削除されます。
つまり、特殊クラスのディレクトリに none クラスのオブジェクトが含まれる場合、pkgrm コマンドでディレクトリを削除しようとすると、ディレクトリが時間内に空にならないので失敗します。none クラスのオブジェクトが特殊クラスのディレクトリに挿入される場合、時間内にオブジェクトを受け入れるディレクトリは存在しません。pkgadd コマンドにより、オブジェクトのインストール時にオンザフライでディレクトリが作成され、最終的に pkgmap 定義を確認した場合にそのディレクトリの属性を同期できない場合があります。
クラスにディレクトリを割り当てる場合は、常に作成と削除の順序を覚えておいてください。