ホーム

rpm-rewrite

English

RPM を作っていて、 インストール時に別パッケージの設定ファイルを書き換えたいと 思ったことはありませんか。 そして、設定ファイルへの書き加えは簡単でも、 アンインストール時にそれを削除しようとすると、 極端に繁雑なスクリプトを書かないといけないことに気がつきませんでしたか。

rpm-rewrite-0.5.tar.gz はこの問題を解決します。 すなわち、spec 内で設定ファイルの書き換えを簡単にする方法を提供します。


Syntax sugar

 インストール時に、/etc/hoge というファイルに 次のような1行を書き加えたいとしましょう。

use fugafuga

 そしてアンインストール時には元に戻したいとしましょう。 あなたならどうしますか?

 もしも spec に次のような文法が存在すればどうでしょう。

%rewrite /etc/hoge << EOF
use fugafuga
EOF

 rpm-rewrite.pl は、このような表記を、 %triggerin/%triggerun を用いた表記に翻訳します。


SPEC 文法拡張

 正確には、上の表記ではうまくいきません。

 などの情報も必要です。従って、次のような文法にしてみました。

%rewritetrigger -- hogehoge        パッケージ名
%rewrite /etc/hoge #      書き換えるファイル名とコメント記号
use fugafuga                                  書き加える内容
#             もう一度コメント記号 - 書き加える内容の終了
%rewritein                    書き加え後に実行するスクリプト
echo "rewrited /etc/hoge .. add 'use fugafuga'"
%rewriteun                        削除後に実行するスクリプト
echo "rewrited /etc/hoge .. remove 'use fugafuga'"

 実際には /etc/hoge には次のように追記されます。 最初と最後の行は、削除用のマークです。

# Do not edit this line - begin fugafuga-1-1-1
# This part was added and will be removed by RPM automatically.
use fugafuga
# Do not edit this line - end fugafuga-1-1-1

 rpm-rewrite.pl で生成する spec を大きく単純化すると、次のような感じになります。

%triggerin -- hogehoge
if [ -e /etc/hoge ]; then
cat <<EOF>>/etc/hoge
# Do not edit this line - begin %{name}-%{version}-%{release}
# This part was added and will be removed by RPM automatically.
use fugafuga
# Do not edit this line - end %{name}-%{version}-%{release}
EOF
echo "rewrited /etc/hoge .. add 'use fugafuga'"
fi

%triggerun -- hogehoge
if [ -e /etc/hoge ]; then
cp -af /etc/hoge /etc/hoge.rpmtmp && \
    sed -e '/^# Do not edit this line - begin %{name}-%{version}-%{release}$/,/^# Do not edit this line - end %{name}-%{version}-%{release}$/d' \
    < /etc/hoge.rpmtmp > /etc/hoge
echo "rewrited /etc/hoge .. remove 'use fugafuga'"
fi

 %triggerin を使うのは、 /etc/hoge の属するパッケージがバージョンアップされた場合でも、 設定ファイルの書き換えを再度行うためです。

 削除時には、ファイルの所有者や属性を保存するために、 リダイレクトで元のファイルを上書きしています。

 しかし、この程度のことでは、うまく動きません。 'rpm -U' の動作や --force オプションがついた時の動作を考慮すると、どんどん複雑になります。


実際に生成される SPEC

 まず、rpm-rewrite で生成した SPEC は、 何度でも rpm-rewrite に通せることを目指しました。 つまり、SPEC 内に元の表記を保存することにします。


 'rpm -U' 時の動作は複雑で、 新パッケージのインストールの後に旧パッケージの削除が行われます。 update すると、せっかくの書き換えが消滅してしまうかもしれないのです。

 update 時には %triggerun 内で $1 が 1 になることを利用して、 その時にはなにもしないという方法も考えられます。 しかし、これはやりたくありません。 update 後のパッケージでは、ファイルの書き換えをやめているかもしれません。 そうすると、追記は永遠にそのままになってしまいます。

 追記した内容をそのパッケージの %triggerun で削除することを第一に考えると、 削除用のマークに、パッケージのバージョン番号を含めればよいことに気がつきます。 しかしこれでも十分ではありません。 トリガー対象のパッケージの update では、 同じバージョンで %triggerin と %triggerun が実行されます。 もちろん、トリガー対象のパッケージの update であることを、 スクリプト内で見分ける方法があります。$2 を使います。


 削除用のマークに $2 の値も書き込むことで、 ようやく満足に追記削除が行えるようになったと思えます。 思えるのですが、もう1つだけ問題を見つけました。

 --force オプションつきで 'rpm -U' を行うとすると、 同一バージョンのパッケージを何度でもインストールできてしまいます。 幸い、この場合は %treiggerun は実行されません。 %treiggerin で、まずは削除動作を行ってから追記すれば解決します。


 まだまだ問題はありそうな気もします。 とにかく気のついている問題は以上で、 これらについては解決しているはずです。


perl スクリプトと配布物

 このような SPEC を生成する perl スクリプトを作りました。

 'rpm -tb rpm-rewrite-0.5.tar.gz' で RPM を作ることができます。

 使い方は、以下の通りです。

usage1: rpm-rewrite.pl < old.spec > new.spec
usage2: rpm-rewrite.pl < new.spec > even_new.spec


動作チェック

 2つのパッケージを考えます。p1 と p2 としましょう。 それぞれ /etc/p1 と /etc/p2 という設定ファイルを所有して、 互いに書き直すことにします。 p2 の設定ファイルには (noreplace) 属性をつけて、 バージョンアップでも書き換えないようにします。

 p1 p2 にそれぞれ2つずつのバージョンを用意して、

 での書き換えがうまくいくか確かめます。

 build-test-rpm.shp11.spec から4つの RPM を作ります。 test-rpm.sh でこのテストを行います。


これからの予定


ホーム
リンクはご自由にどうぞ。
土村 展之(tutimura(a)nn.iij4u.or.jp) '(a)'は'@'に置き換えて
更新日 5/25 23:00, 2002