uchan note

プログラミングや電子工作の話題を書きます

deb パッケージングメモ - alien 編

Ubuntudeb パッケージを作ろうとして調べ、実験したメモです。

なぜ自作ツールdeb パッケージを作るのか

開発したソフトウェアを Chef や Ansible などでデプロイするのに、apt-get install できると便利です。 deb にすることで、プログラム本体だけでなく、正しく動かすために必要なもろもろを deb 製作側の責任で作り込むことができます。 依存関係を考慮してくれたり、アップデートやアンインストールが容易なことも魅力です。

自作のプログラムに加え、Oracle Java のように tar.gz または rpm でしか提供されていないものを deb 化したいという需要もあります。

deb 化の方法の選択肢

プログラムを deb 化するに当たって、幾つかのやり方があります。

  • alien コマンドを使う
  • 正攻法でビルドする

alien

alien は tar.gz や rpm 形式のアーカイブを deb に変換するコマンドです。

tar.gz も rpmdeb も、基本的にはインストールするファイルをまとめて圧縮したものです。 したがって、ビルド済みのプログラムを含むアーカイブなら、簡単に変換できます。 Oracle Javadeb 化にはこの方法が合っていると思われます。

正攻法

dh_make や pdebuild を使い、ソースコードから deb パッケージを生成する方法です。

正攻法を正しく行うには事前の学習がそれなりに必要ですが、ビルド済みアーカイブがなくても良い点や、コンテナを用いたクリーンビルドができる点が優れています。 また、alien ではメタデータを細かく調整できなかったりしますが、正攻法ではその心配はありません。

正攻法はこの記事では扱いません。後日、別記事で書くかもしれません。書かないかもしれません。

alien を使って tar.gz から deb を作る

Oracle Java 8 JDK を例に、ビルド済みバイナリの tar.gz アーカイブを deb に変換する方法を紹介します。

まずはそのまま変換してみる

変換元のアーカイブが jdk-8u73-linux-x64.tar.gz であるとします。まずファイル名を希望するパッケージ名に変えます。

$ mv jdk-8u73-linux-x64.tar.gz oraclejdk8-jdk.tar.gz

Ubuntuリポジトリにある OpenJDK 7 のパッケージ名は openjdk-7-jdk なので、それに合わせて oraclejdk-8-jdk というように 8 の前にハイフンを入れたくなります。しかし、alien の制約で、数字の前にハイフンがあるとその数字以降が無視されてしまいます。恐らく、バージョン番号だから無視すべきと判断しているのでしょう。したがって、8 の前にはハイフンを入れない名前にしました。

いよいよ deb に変換します。

$ sudo alien -v --version=1.8.0.73 --bump=0 oraclejdk8-jdk.tar.gz

alien コマンドは root ユーザを要求します。sudo または fakeroot とともに実行してください。

出来上がったパッケージのバージョンを指定するのに --version オプションを使います。また、パッケージのリビジョン(debian バージョン)を指定するのに --bump オプションを使います。

--bump は変換元のリビジョンに加算する数値を指定するオプションで、デフォルトでは 1 です。tar.gz にはもともとリビジョン(およびバージョンも)がありませんから、リビジョンとして 1 が指定されているとみなされます。したがって、--bump を指定せずに実行すると oraclejdk8-jdk_1.8.0.73-2_amd64.deb というファイルが生成されます。

最初のパッケージなのにリビジョンが 2 になるのは気持ち悪いですね。ということで、例では --bump=0 として、リビジョンを増加させないように指示しています。oraclejdk8-jdk パッケージを一度でも外部に出した後、同じバージョンでビルドしなおすときは --bump を増やしましょう。リビジョンを上げておけば、APT の仕組みでアップグレードされるようになります。

alien コマンドがどのような処理をしているかを見たいので -v オプションを付けましたが、これは付けなくても動作は変わりません。

最後に出来上がったパッケージの中身を確認してみます。

$ dpkg -c oraclejdk8-jdk_1.8.0.73-1_amd64.deb | less

パッケージをインストールすると、ここで表示されたパスにファイルが配置されます。すべてのファイルが /jdk-1.8.0_73/ 以下に配置されることが分かりました。このパスは通常使われるインストール先ではありません。後ほど、ルートディレクトリを調整する方法を紹介します。

インストールスクリプトを含ませてみる

rpmdeb はインストール前後に実行するスクリプトを含むことができます。スクリプトを使うと例えば、配置したバイナリを update-alternatives に登録したりできます。

これをやるには、一旦アーカイブを展開し、スクリプトを含めた DEBIAN ディレクトリとともに圧縮しなおします。(アーカイブのファイル名は元に戻した前提で話を進めます。)

$ tar xzf jdk-8u73-linux-x64.tar.gz
$ mkdir DEBIAN
$ vim DEBIAN/postinst
$ chmod +x DEBIAN/postinst

postinst はインストールの後処理で呼ばれるスクリプトです。ファイルがすべて配置し終わった後に呼び出されます。 postinst の中身はなんでもいいですが、例えばこんな感じにしてみましょうか。

#!/bin/sh
for f in $(ls /jdk-1.8.0_73/bin/*); do
    update-alternatives --install /usr/bin/$f $f /jdk-1.8.0_73/bin/$f 1
done

このスクリプトはインストールされたすべてのコマンドを update-alternatives に登録します。update-alternatives は、/usr/bin/java などをシンボリックリンクにし、実際に指すコマンドを手軽に切り替えられる仕組みです。

スクリプトを含めた deb パッケージを生成してみます。

$ tar czf oraclejdk8-jdk.tar.gz jdk-1.8.0_73/ DEBIAN/
$ sudo alien -v --version=1.8.0.73 --bump=1 oraclejdk8-jdk.tar.gz

oraclejdk8-jdk_1.8.0.73-2_amd64.deb をインストールしてみると、最後の方で update-alternatives が実行されるのを確認できます。

インストール先を調整してみる

これまでのやり方では、インストール先が /jdk-1.8.0_73 となってあまり綺麗ではありません。標準的には /usr/opt にインストールすることになっていますから、それに従うように調整してみます。

これには、tar で展開するときにオプションを使って調整してしまうのが楽です。

$ mkdir -p opt/oraclejdk8-jdk
$ tar xzf jdk-8u73-linux-x64.tar.gz -C opt/oraclejdk8-jdk --strip-component 1

tar コマンドは -C オプションで展開先を指定できます。さらに --stript-component 1 で先頭から 1 つのパスを削りつつ展開するよう指示しています。これらを組み合わせると opt/oraclejdk8-jdk/bin/java などに展開できます。

インストール先を変えたので、postinst も変更しておきましょう。ls /jdk-1.8.0_73/bin/*ls /opt/oraclejdk8-jdk/bin/* に変えれば OK です。

あとはアーカイブを作り alien を実行するだけです。

$ tar czf oraclejdk8-jdk.tar.gz opt/ DEBIAN/
$ sudo alien -v --version=1.8.0.73 --bump=2 oraclejdk8-jdk.tar.gz
$ dpkg -c oraclejdk8-jdk_1.8.0.73-3_amd64.deb | less

どうでしょうか。/opt/oraclejdk8-jdk 以下にインストール先を変更できたことが分かるはずです。