Linuxプログラムのパッケージ化

4427 ワード

Linuxプログラムのパッケージ化
2012-09-14
最近、コンパイルしたLinuxプログラムをパッケージ化して複数のLinuxリリースにインストールして実行するプロジェクトがあります.異なるリリース版であるため、それぞれのリリース版独自のパッケージフォーマットを使用するのに適していません.特定のリリース版に対しても、異なるバージョンのシステムライブラリバージョンによって共通のパッケージを作成できません.(プログラムはFedora 6のような「古い」バージョンにも、この2年間にリリースされたリリースにもインストールする必要があります.)いくつかのソリューションを比較した後、最終的にパッケージ開発システム上のダイナミックリンクライブラリを選択し、dynamic linkerとダイナミックリンクライブラリディレクトリをスクリプトで指定してパッケージ後のバイナリファイルのシナリオを実行します.
最初に静的リンクを考慮したが,開発用のUbuntuはすべての依存ライブラリの静的リンクバージョンを提供していない.すべてのライブラリを自分で再コンパイルするのは面倒なので、このスキームは使いません.LD_LIBRARY_PATHおよびdynamic linker
その後、CDEを試したことがあります(後で詳しく説明します)、いくつかの制限のため、最後に自分でパッケージすることにしました.これにより、他のツールに依存せず、完全な制御を得ることができます.最初はプログラム依存のダイナミックリンクライブラリを単純に1つのディレクトリの下に見つけて、他のシステムでLD_LIBRARY_PATHを指定すれば正常に使用できると思っていましたが、実際にはまだ一歩足りません.LD_LIBRARY_PATHのみを指定すると、2つのエラーが発生しました.
コンパイルされたbinaryファイルを32/64-bitのシステムで同時に動作させるために、32-bit Ubuntuでコンパイルしました.binaryを64-bitにコピーするシステムで実行中に以下のエラーが発生しました:/lib/ld-linux.so.2: bad ELF interpreter: No such file or directory
32-bitのFedora 6にLD_LIBRARY_PATHが設定後、どのプログラムを実行してもセグメントエラーが発生する.
Googleはその後、Stack Overflowでも2番目の問題に遭遇した人がいることに気づいた.実はこの2つのエラーの原因はdynamic linker(dynamic linking loader)と関係があります.
GNU Cライブラリを使用するシステムでは、ELFファイルの実行時にdynamic linkerが自動的に実行されます(32ビットLinuxでは一般的に/lib/ld-linux.so.2、64ビットでは/lib/ld-linux-x86-64.so.2)、dynamic linkerではLD_LIBRARY_PATHが読み込まれ、指定されたディレクトリの下でshared libraryが見つかります.しかしdynamic linker自身のパスはELFファイルヘッダにハードコーディングされている.
だから64-bitシステムが報告したエラーの本当の意味はdynamic linkerが見つからないことです.このシステムには32-bitのCライブラリがインストールされていないからです.2つ目のエラーは、Fedora 6のdynamic linkerと私がパッケージしたUbuntuのCライブラリが互換性がないためです.(Stack Overflowの回答ではloaderはCライブラリの一部だと言われていますが、互換性がない具体的な原因は不明です.)
この問題を解決する方法は、プログラムの起動に使用するloaderを指定することです.呼び出し方法は次のとおりです.
LD_LIBRARY_PATH=<lib path> /lib/ld-linux.so.2 <executable>
/lib/ld-linux.so.2はdynamic linkerであるため、このような呼び出し方式をサポートする.しかし、LD_LIBRARY_PATH環境変数によってlibrary search pathを指定するには、プロセスがこの環境変数を持つという欠点があります.したがって、プロセスは、システム上の他のコマンドを実行しようとすると、上記の2番目の問題に遭遇する可能性があります.実際にはLD_LIBRARY_PATHという環境変数をできるだけ避けるべきで、Why LD_を参照してください.LIBRARY_PATH is bad.
dynamic linkerでは、library search pathを次のようにパラメータで指定できます.
/lib/ld-linux.so.2 --library-path <lib path> <executable>

dynamic linkerにパラメータを指定するとLD_LIBRARY_PATHは無視されます.
dynamic linkerの問題を知った後、パッケージの残りの仕事はdynamic linkerで実行可能ファイルを起動するためにスクリプトを修正することです.
コンパイル時にlibrary pathとdynamic linkerを指定する
パブリッシュされたプログラムがshellで頻繁にインタラクティブに使用される場合、実行するたびにdynamic linkerを指定するのは不便です.実際にdynamic linkerとlibrary path情報はELFヘッダに保存されており、プログラムはリンク時にこれらの情報を指定することができます.
library pathは、--rpath=<path list>パラメータをリンクに渡すことによって指定することができ、dynamic loaderは--dynamic-linker=<path to loader>によって指定される.gccによってlinkerが呼び出される場合、-Wl,によってlinkerにオプションを渡すことができます.以下のようにします.
gcc ... -Wl,--rpath=<path list> -Wl,--dynamic-linker=<path to loader>

得られたELFファイルヘッダ情報は、readelf -a <executable>を使用して表示できます.INTERPはdynamic linkerを指定し、RPATHはlibrary search pathを指定します.
configureスクリプトを変更したくないので、私は最後にこの方法を採用しませんでした.
CDE
実はLinuxのパッケージの問題は以前から解決しようとした人がいました.この間Philip J.GuoのThe Ph.D.Grindを読みました.彼の博士時代の仕事Code Data Environment(CDE)は、アプリケーションのために独自のパッケージを作成し、他のLinuxシステムに公開して実行します.CDEの論文を一目見たところ、その最も主要な動作メカニズムは、ptraceを使用してシステム呼び出しをブロックし、プログラムに依存するファイルおよびシステム環境(例えば環境変数)をキャプチャすることである.単純化のためプログラム依存のファイルのみを考慮し、CDEは以下のように動作します.
パッケージを作成するとき、実行プログラムは、openのようなシステム呼び出しを同時にブロックし、アプリケーションがどのファイルを使用するかを見て、パッケージディレクトリの下にコピーまたはリンクする.
配備されたシステム上で実行する場合、同様にopen呼び出しをブロックし、の代わりに開こうと試みるファイルをパッケージディレクトリの下のファイルに置き換える.
この原理は簡単で効果的で、CDEは実際に使用してもとても便利だと思います.10分以内にFedora 6のvimを別のDebian 6にインストールして正常に使用することに成功しました.いくつかのニーズにとって、CDEはLinux dependency hellを解決する便利なツールとして使用することができます.
しかし、CDEパッケージ後のプログラムはsandboxで実行され、seamless execution modeを使用しない限りsandbox以外のファイルにアクセスできません.しかし、seamless execution modeを正常に動作させるにはtricky、CDEは私にとって新しいツールなので、理解が足りないのではないかと心配してdebugに時間がかかりすぎて採用しませんでした.(CDEはアプリケーションを実行する際にptraceのモニタを使用する必要があり、プログラムの実行性能に少し影響しますが、影響は大きくなく、私のアプリケーションにとって性能は主な問題ではありません.)
Shared Library関連資料
Program Library HOWTO、shared libraryを紹介する良い文章です.ここは私が作ったメモです.
Posted by Chen Yufei 2012-09-14  linux