5.3. Epoch、Scriptlets、Triggers

このセクションでは、RMP SPEC ファイルの高度なディレクティブを表す EpochScriptletTriggers について説明します。

これらのディレクティブはすべて、SPEC ファイルだけでなく、生成された RPM がインストールされているエンドマシンにも影響します。

5.3.1. Epoch ディレクティブ

Epoch ディレクティブでは、バージョン番号に基づいて加重依存関係を定義できます。

このディレクティブが RPM SPEC ファイルにない場合、Epoch ディレクティブは全く設定されません。これは、Epoch を設定しないと Epoch が 0 になるという一般的な考え方に反しています。ただし、dnf ユーティリティーは、depsolve の目的で、0 の Epoch と同様に設定されていない Epoch を処理します。

ただし、SPEC ファイルでの Epoch の リストは通常省略されます。これは、多くの場合、Epoch 値を導入すると、パッケージのバージョンを比較する際に、想定される RPM 動作がスキューされるためです。

例5.2 Epoch の使用

Epoch: 1Version:1.0 で foobar パッケージをインストールし、別のユーザーが foobarVersion: 2.0 でインストールした場合、Epoch ディレクティブがないと、新しいバージョンが更新と見なされることはありません。RPM パッケージ用のバージョン管理を示す従来の Name-Version-Release ラッパーよりも、Epoch バージョンが推奨されている理由。

Epoch を使用することはほとんどありません。ただし、Epoch は 、通常、アップグレードの順序の問題を解決するために使用されます。この問題は、ソフトウェアバージョン番号のスキームや、エンコードに基づいて確実に比較できないアルファベット文字を組み込んだバージョンにおける、アップストリームによる変更の副次的効果として見られる場合があります。

5.3.2. Scriptlets ディレクティブ

Scriptlets は、パッケージがインストールまたは削除される前または後に実行される一連の RPM ディレクティブです。

Scriptlets は、ビルド時またはスタートアップスクリプト内で実行できないタスクにのみ使用します。

共通の Scriptlet ディレクティブのセットがあります。これは、SPEC ファイルセクションのヘッダー (%build%install など) と似ています。これは、標準の POSIX シェルスクリプトとしてよく書かれる、マルチラインのコードセグメントによって定義されます。ただし、ターゲットマシンのディストリビューションの RPM が対応する他のプログラミング言語で書くこともできます。RPM ドキュメントには、利用可能な言語の完全なリストが含まれます。

以下の表には、実行順の Scriptlet ディレクティブのリストが含まれます。スクリプトを含むパッケージは、%pre%post ディレクティブの間にインストールされ、%preun ディレクティブと %postun ディレクティブ間でアンインストールされることに注意してください。

表5.2 Scriptlet ディレクティブ

ディレクティブ定義

%pretrans

パッケージのインストールまたは削除の直前に実行されるスクリプトレット。

%pre

ターゲットシステムにパッケージをインストールする直前に実行されるスクリプトレット。

%post

ターゲットシステムにパッケージがインストールされた直後に実行されるスクリプトレット。

%preun

ターゲットシステムからパッケージをアンインストールする直前に実行されるスクリプトレット。

%postun

ターゲットシステムからパッケージをアンインストールした直後に実行されるスクリプトレット。

%posttrans

トランザクションの最後に実行されるスクリプトレット。

5.3.3. スクリプトレット実行の無効化

以下の手順では、rpm コマンドと --no_scriptlet_name_ オプションを使用して、スクリプトレットの実行を無効にする方法を説明します。

手順

  • たとえば、%pretrans スクリプトレットの実行を無効にするには、次のコマンドを実行します。

    # rpm --nopretrans

    -- noscripts オプションも使用できます。これは、以下のすべてと同等になります。

    • --nopre
    • --nopost
    • --nopreun
    • --nopostun
    • --nopretrans
    • --noposttrans

関連情報

  • rpm(8) man ページ

5.3.4. スクリプトレットマクロ

Scriptlets ディレクティブは、RPM マクロでも機能します。

以下の例は、systemd スクリプトレットマクロの使用を示しています。これにより、systemd は新しいユニットファイルについて通知されるようになります。

$ rpm --showrc | grep systemd
-14: __transaction_systemd_inhibit      %{__plugindir}/systemd_inhibit.so
-14: _journalcatalogdir /usr/lib/systemd/catalog
-14: _presetdir /usr/lib/systemd/system-preset
-14: _unitdir   /usr/lib/systemd/system
-14: _userunitdir       /usr/lib/systemd/user
/usr/lib/systemd/systemd-binfmt %{?*} >/dev/null 2>&1 || :
/usr/lib/systemd/systemd-sysctl %{?*} >/dev/null 2>&1 || :
-14: systemd_post
-14: systemd_postun
-14: systemd_postun_with_restart
-14: systemd_preun
-14: systemd_requires
Requires(post): systemd
Requires(preun): systemd
Requires(postun): systemd
-14: systemd_user_post  %systemd_post --user --global %{?*}
-14: systemd_user_postun        %{nil}
-14: systemd_user_postun_with_restart   %{nil}
-14: systemd_user_preun
systemd-sysusers %{?*} >/dev/null 2>&1 || :
echo %{?*} | systemd-sysusers - >/dev/null 2>&1 || :
systemd-tmpfiles --create %{?*} >/dev/null 2>&1 || :

$ rpm --eval %{systemd_post}

if [ $1 -eq 1 ] ; then
        # Initial installation
        systemctl preset  >/dev/null 2>&1 || :
fi

$ rpm --eval %{systemd_postun}

systemctl daemon-reload >/dev/null 2>&1 || :

$ rpm --eval %{systemd_preun}

if [ $1 -eq 0 ] ; then
        # Package removal, not upgrade
        systemctl --no-reload disable  > /dev/null 2>&1 || :
        systemctl stop  > /dev/null 2>&1 || :
fi

5.3.5. Triggers ディレクティブ

Triggers は、パッケージのインストールおよびアンインストール時に対話できる手段を提供する RPM ディレクティブです。

警告

Triggers は、含まれるパッケージの更新など、予期できないタイミングで実行できます。Triggers はデバッグが難しいため、予期せず実行されたときに破損しないように、安定したな方法で実装する必要があります。このため、Red Hat では、Trigger の使用は最小限に抑えることを推奨します。

1 つのパッケージアップグレードの実行順序と、既存の各 Triggers の詳細は、以下のとおりです。

all-%pretrans
…​
any-%triggerprein (%triggerprein from other packages set off by new install)
new-%triggerprein
new-%pre      for new version of package being installed
…​           (all new files are installed)
new-%post     for new version of package being installed

any-%triggerin (%triggerin from other packages set off by new install)
new-%triggerin
old-%triggerun
any-%triggerun (%triggerun from other packages set off by old uninstall)

old-%preun    for old version of package being removed
…​           (all old files are removed)
old-%postun   for old version of package being removed

old-%triggerpostun
any-%triggerpostun (%triggerpostun from other packages set off by old un
            install)
…​
all-%posttrans

上記の項目は、/usr/share/doc/rpm-4.*/triggers ファイルにあります。

5.3.6. SPEC ファイルでのシェルスクリプト以外のスクリプトの使用

SPEC ファイルの -p スクリプトレットオプションを指定すると、ユーザーはデフォルトのシェルスクリプトインタープリター (-p /bin/sh) の代わりに特定のインタープリターを起動することができます。

次の手順では、pello.py プログラムのインストール後にメッセージを出力するスクリプトの作成方法を説明します。

手順

  1. pello.spec ファイルを開きます。
  2. 以下の行を見つけます。

    install -m 0644 %{name}.py* %{buildroot}/usr/lib/%{name}/
  3. 上記の行の下に、以下を挿入します。

    %post -p /usr/bin/python3
    print("This is {} code".format("python"))
  4. RPM のビルド の説明に従ってパッケージをビルドします。
  5. パッケージをインストールします。

    # dnf install /home/<username>/rpmbuild/RPMS/noarch/pello-0.1.2-1.el8.noarch.rpm
  6. インストール後に出力メッセージを確認します。

    Installing       : pello-0.1.2-1.el8.noarch                              1/1
    Running scriptlet: pello-0.1.2-1.el8.noarch                              1/1
    This is python code
注記

Python 3 スクリプトを使用するには、SPEC ファイルの install -m に次の行を含めます。

%post -p /usr/bin/python3

Lua スクリプトを使用するには、SPEC ファイルの install -m に次の行を含めます。

%post -p <lua>

これにより、SPEC ファイル内で任意のインタープリターを指定できます。