home ホーム search 検索 -  login ログイン  | reload edit datainfo version cmd icon diff delete  | help ヘルプ

技術/Linux/RPMパッケージの作成(no-build) (v1)

技術/Linux/RPMパッケージの作成(no-build) (v1)

技術 / Linux / RPMパッケージの作成(no-build) (v1)
id: 1295 所有者: msakamoto-sf    作成日: 2014-06-08 19:27:41
カテゴリ: Linux 

技術/Linux/RPMコマンドメモ(パッケージ作成など) で簡単ながらパッケージ作成時のTipsをまとめているが、今回はビルドを伴わないパッケージの作成方法について勉強してみた。
今回の「ビルドを伴わないパッケージ」というのは、リポジトリやtarボールから展開して適切な場所にファイル・ディレクトリを配置するだけで良いファイルセットをRPMパッケージにすることを指す。PHPスクリプトや、設定ファイルなどでこのようなケースが該当する。
サンプルを作成してみたので、ポイントとなる箇所を解説していく。

サンプル:

今回の練習環境:

CentOS 6.5 x86_64版
$ rpm --version
RPM version 4.8.0
$ rpmbuild --version
RPM version 4.8.0

ソース構成:

rpmbuild-demo-without-compilation/
├── buildrpm.sh                  ... ビルド時の一時的なtarボールの生成とrpmbuildの実行スクリプト
├── helloworld/                  ... 設定ファイルのセットで、これを"/etc"以下にインストールするRPMを作成する
│   ├── auto_include_child/
│   │   ├── regular1.txt
│   │   └── regular2.txt
│   ├── dir_only
│   │   └── ignored.txt
│   ├── greet.conf
│   ├── greet-noreplace.conf
│   ├── greet.sh
│   ├── p0600.txt
│   ├── p0705.txt
│   └── regular.txt
├── helloworld.spec              ... SPECファイル
├── LICENSE
└── README.md

ビルド方法

# yum install rpm-build

$ cd /home/msakamoto/work
$ git clone git@github.com:msakamoto-sf/rpmbuild-demo-without-compilation.git

# 以下はJenkinsなどCI環境からのビルドを意識して、サブシェルによりcdしてから buildrpm.sh を起動する例
$ cd /
$ (cd /home/msakamoto/work/rpmbuild-demo-without-compilation && ./buildrpm.sh)

buildrpm.shのポイント

  • specファイルが参照するtarボールを、スクリプト実行時に動的に生成する。
    • スクリプトの簡略化のためと、一時的なものであるため、tarボールのファイル名にバージョン情報等は含めない。極端な話、プロジェクトとは何の関係のない "foo.tar.gz" とかでも spec ファイルの SourceN と一致していれば問題ない。
  • buildrpm.sh と同じディレクトリをカレントディレクトリとして実行することを前提とする。
    • tarボールを作成するときのアーカイブ内のファイルパスの調整のため。
    • もちろん、tarをサブシェルに押し込んで、"(cd /xxx/yyy/zzz && /bin/tar czf ...)" とすれば、カレントディレクトリの依存性を排除することも可能だろう。
  • rpmbuildで重要な "_topdir" マクロを、rpmbuildコマンドの "--define" により動的に指定。
    • これにより、 "$HOME/.rpmmacros" への依存性を排除できる。JenkinsなどのCI環境でのビルドにも柔軟に対応できる。
#!/bin/sh
WORK_DIR=`pwd`
BUILD_NAME=helloworld
BUILD_SPEC=${BUILD_NAME}.spec
BUILD_TAR=${BUILD_NAME}.tar.gz
BUILD_DIR=${WORK_DIR}/rpmbuild
BUILD_TAR_PATH=${WORK_DIR}/rpmbuild/SOURCES/${BUILD_TAR}

/bin/rm -rf ${BUILD_DIR}

# rpmbuildが使用する各種ビルドディレクトリを作成
/bin/mkdir -p ${BUILD_DIR}/{BUILD,RPMS,SOURCES,SPECS,SRPMS}

# rpmbuildのためだけの、一時的なtarボールを生成してSOURCESに配置
/bin/tar czf ${BUILD_TAR} ${BUILD_NAME}/
/bin/mv ${BUILD_TAR} ${BUILD_TAR_PATH}

# "$HOME/.rpmmacros" に依存せずに rpmbuild を実行
/usr/bin/rpmbuild --define "_topdir ${BUILD_DIR}" -bb ${BUILD_SPEC}

helloworld.specファイルのポイント

今回のspecファイルとソースツリーについては、以下の記事を参考にさせて頂いております。helloworldのパッケージ名やディレクトリ構成など、丸パクリさせてもらいました。

"Name", "Version", "Release" については難しく無い。"Group"については、可能であれば既に存在するグループ名を指定する方が良いらしい。CentOSであれば、"yum grouplist" でCentOSで利用可能なグループ名の一覧を取得できる。

Name:      helloworld
Version:   1.0
Release:   1
Group:     Security Tools

参考:

"Vendor"は、個人ではなく会社等でパッケージを開発する際は入れておいたほうが良いだろう。"URL", "License", "Summary"はそのまま。"BuildArch" については、今回は単なる設定ファイルのパッケージングなので "noarch" を指定した。

Vendor:    Example Company Inc.
URL:       http://www.example.com/
License:   Custom License
Summary:   Example RPM Plain File Packaging.
BuildArch: noarch

ソースの指定で、ここでrpmbuild.shが一時的に生成したtarボール名を指定している。

# use build-time generated tar ball.
Source0:   %{name}.tar.gz

"BuildRoot"については、最近のRHEL系rpmbuildでは無視されるようだ。RHEL5系以前との互換性のために、一つのシステム上で複数人 or 複数ジョブが同時にビルドしても衝突しないよう、mktempでユニークな一時ファイル名を生成している。なお、今回実験した環境では "rpmbuild/BUILDROOT" というディレクトリが自動的に作成され、それが "%{buildroot}" として参照できていた。

# (only create temporary directory name, for RHEL5 compat environment)
# see : http://fedoraproject.org/wiki/Packaging:Guidelines#BuildRoot_tag
BuildRoot: %(mktemp -ud %{_tmppath}/%{name}-%{version}-%{release}-XXXXXX)

BuildRootの解説と、最近のrpmbuildではdeprecatedになった話についての参考:

"%install" で指定する、ファイルツリーの展開先。"%{buildroot}" がインストール先のルートディレクトリに相当する。今回は helloworld を "/etc/helloworld" 以下に展開したいため、そのように調整している。

%define INSTALLDIR %{buildroot}/etc/helloworld

パッケージの説明以降は、準備とビルド(今回は何もしない)、仮のインストール、クリーニング処理になる。ファイルコピーについては、tarボール中のファイルパス名と、"%prep"でのファイル展開先との兼ね合いで微調整が必要になる。最後に"%{buildroot}"を削除している。

%description
%{summary}

%prep
%setup -q -n %{name}

%build

%install
rm -rf %{INSTALLDIR}
mkdir -p %{INSTALLDIR}
cp -Rp * %{INSTALLDIR}

%clean
#rm -rf %{buildroot}
# Avoid Disastarous Damage : http://dev.tapweb.co.jp/2010/12/273
[ "$RPM_BUILD_ROOT" != "/" ] && rm -rf $RPM_BUILD_ROOT

"%files"では、属性の付け方や、"%config"の動きを練習してみた。また、正式にドキュメント化はされていないようだが、"%exclude"により、特定のファイルを除外する方式も試している。"%dir"と組み合わせており、「git向けに空ディレクトリとして、無視ファイル1つだけ入れたディレクトリをリポジトリに登録したが、パッケージインストール時はディレクトリだけを作成して終わりにしたい」というユースケースを想定している。

%files
%defattr(-,root,root)
/etc/helloworld/regular.txt

# auto include child files under the directory
/etc/helloworld/auto_include_child

%config %attr(0600,root,root) /etc/helloworld/greet.conf
%config(noreplace) /etc/helloworld/greet-noreplace.conf

%attr(0700,root,root) /etc/helloworld/greet.sh
%attr(0600,root,root) /etc/helloworld/p0600.txt
%attr(0705,root,root) /etc/helloworld/p0705.txt

# directory only
%dir %attr(0770,-,-) /etc/helloworld/dir_only
%exclude /etc/helloworld/dir_only/ignored.txt

"%files", "%attr"参考:

"%exclude"について:

最後に、pre/post, preun/postun についての練習を入れている。

%pre
if [ "$1" = "1" ]; then
  echo "pre-install script : Initial installation."
elif [ "$1" = "2" ]; then
  echo "pre-install script : Upgrade installation."
fi

%post
if [ "$1" = "1" ]; then
  echo "post-install script : Initial installation."
elif [ "$1" = "2" ]; then
  echo "post-install script : Upgrade installation."
fi

%preun
if [ "$1" = "0" ] ; then
  echo "pre-uninstall script : Uninstall operation."
elif [ "$1" = "1" ]; then
  echo "pre-uninstall script : Upgrade uninstallation process."
fi

%postun
if [ "$1" = "0" ] ; then
  echo "post-uninstall script : Uninstall operation."
elif [ "$1" = "1" ]; then
  echo "post-uninstall script : Upgrade uninstallation process."
fi

%changelog

参考資料

RPMの基本

Fedoraからのドキュメント、パッケージングのガイドライン

今回、かなり参考になった記事

JenkinsなどCI環境と組み合わせる場合に参考になりそうな記事

Rubyなどのライブラリから、RPMパッケージをプログラマブルに生成するライブラリ

その他



プレーンテキスト形式でダウンロード
現在のバージョン : 1
更新者: msakamoto-sf
更新日: 2014-06-08 21:25:54
md5:44ee886411fc78978cb2d366d616a06c
sha1:68858e2729b43f60045f26e3875d39513ae97707
コメント
コメントを投稿するにはログインして下さい。