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 文法拡張
正確には、上の表記ではうまくいきません。
- /etc/hoge の属するパッケージ名
- /etc/hoge に記述できるコメント開始記号
- 書き換え後に実行するスクリプト
などの情報も必要です。従って、次のような文法にしてみました。
%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-rewrite.pl
- 配布物全体 rpm-rewrite-0.5.tar.gz
'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.sh は p11.spec から4つの RPM を作ります。 test-rpm.sh でこのテストを行います。
これからの予定
- 英語ドキュメント
- PreReq: sed をチェック
- %triggerin/un のパッケージ名重複チェック
- .rpmnew の面倒も見ないといけない気がしてきた...
ホーム
リンクはご自由にどうぞ。 |
土村 展之(tutimura(a)nn.iij4u.or.jp) '(a)'は'@'に置き換えて 更新日 5/25 23:00, 2002 |