- LD_LIBRARY_PATH は、標準のシステム パスではなく共有ライブラリを検索する場所をダイナミック ローダーに指示します。
- グローバルに使用すると、セキュリティ上の欠陥、パフォーマンスの低下、デバッグが困難な非互換性が生じる可能性があります。
- 特定のアプリケーションへの影響を制限するには、-rpath、LD_RUN_PATH、またはラッパー スクリプトなどの代替手段を使用することをお勧めします。
- LD_LIBRARY_PATH を特定のテストまたは制御された環境でのみ定義すると、隠れた依存関係や予期しない動作を回避できます。
LD_LIBRARY_PATHは、Linux の環境変数の中でも、誰もが遅かれ早かれ目にすることになるものの、その意味を完全に理解している人はごくわずかで、しかも頻繁に誤用されている変数の一つです。共有ライブラリ、起動しない実行ファイル、独自のライブラリを必要とするアプリケーションなどで問題に直面した際、この名前が何度も頭をよぎります。
この記事では、LD_LIBRARY_PATHとは何か、動的ローダーの内部動作、この変数を使用するのが適切な場合、そして使用を避けるべき場合について解説します。Ubuntuなどのディストリビューションにおける具体的な例(ほぼすべてのディストリビューションに適用可能)を取り上げ、正しい設定方法を説明するとともに、この変数をユーザープロファイルに永続的に紐付けるよりも、はるかにクリーンで安全な代替手段についても紹介します。
LD_LIBRARY_PATH とは何ですか? また、実際には何に使用されますか?

現代のGNU/Linuxシステムでは、ほとんどのプログラムは 共有ライブラリ 実行ファイルの起動時にメモリにロードされるライブラリ(.soファイル)です。実行時にこれらのライブラリを見つけるコンポーネントは ダイナミックチャージャー (通常 ld.so または以下のようなバリエーション ld-linux-x86-64.so.2 アーキテクチャに応じて異なります。
環境変数 LD_LIBRARY_PATHはディレクトリのリストを定義します プログラムの起動時にダイナミックローダーが共有ライブラリを探す場所です。コロンで区切られたリストで、例えば以下のようなものです。 /ruta/uno:/ruta/dos:/otra/rutaそしてそれは相談される 標準ルートの前に システムの /lib o /usr/lib.
これはつまり、LD_LIBRARY_PATH 内のライブラリがシステムディレクトリ内の別のライブラリと同じ名前の場合、ローダーは LD_LIBRARY_PATH 内のライブラリを優先するということです。これが強力な機能であると同時に、不用意に使用すると多くの問題を引き起こす原因にもなります。
この仕組みは、非標準のライブラリパスを扱う場合に特に役立ちます。例えば、Nixのような環境、ユーザーディレクトリへのインストール、ライブラリのカスタムバージョン、あるいはシステムライブラリから取得したくない独自の依存関係を持つアプリケーションなどが挙げられます。
LD_LIBRARY_PATHの一般的な使用例

LD_LIBRARY_PATH の使用は、非常に限定された、管理された状況においてのみ有効です。こうしたケースに限定して使用すれば、非常に便利なツールとなります。しかし、あらゆる状況でデフォルトの解決策として使用してしまうと、遅かれ早かれ何らかの問題が発生するでしょう。
最も一般的な用途の一つは 共有ライブラリの新しいバージョンを試す システムライブラリに触れることなく、コンパイル済みのアプリケーションと競合させることができます。例えば、 libmylib.so ホームディレクトリでは、テストセッションのみが使用するように LD_LIBRARY_PATH を調整できます。
もう1つのよくあるシナリオは、古いバージョンを保持するためにライブラリを移動することです。レガシーアプリケーション用に古いバージョンのライブラリを保持し、システムの他の部分では新しいバージョンを使用したい場合を考えてみましょう。LD_LIBRARY_PATHを使用すると、その特定のアプリケーションに対して、古いバージョンを保存したディレクトリを指定できます。
また、大規模アプリケーション向けに、ベンダーがシステムライブラリに依存せず、独自のライブラリをフォルダ内にパッケージ化する、自己完結型で再配置可能な環境を構築するためにもよく使用されます。このような場合、通常は起動スクリプトによってLD_LIBRARY_PATHが調整され、アプリケーションが常に独自の.soファイルをロードするようになります。
これらのすべての場合において重要なのは、LD_LIBRARY_PATH が、ユーザーが実行するすべてのものやシステム全体に影響を与えるグローバル変数としてではなく、特定のアプリケーションまたはテスト環境に関連付けられた、限定的かつ特定の方法で使用されるということです。
LinuxでLD_LIBRARY_PATHを段階的に設定する方法

リスクを知っていても、 ユーザー環境でLD_LIBRARY_PATHを定義するUbuntuのようなディストリビューションでは、ファイルを編集するのが一般的です。 ~/.bashrc (デフォルトのシェルとしてBashを使用している場合)。これは、新しい対話型ターミナルを開くたびに実行されるファイルです。
まずファイルを開きます お気に入りのエディタで.bashrc多くのチュートリアルで使用されています nano 簡単に言うと、 vi, vim または任意のテキストエディタ:
ナノ〜/ .bashrc
開いたら、変数を設定するエクスポート行を追加する必要があります。ここで重要なのは、等号の周りにスペースを入れないことです。そうしないと、Bash が正しく解釈しません。正しい例は次のとおりです。
LD_LIBRARY_PATH=/home/osboxes/mukul をエクスポートします。
この場合、共有ライブラリを検索する際に、標準ディレクトリよりも先に/home/osboxes/mukulディレクトリを考慮するようにシステムに指示しています。このパスは、カスタムの .so ファイルや使用したいライブラリへのパスに置き換えることができます。
変更を保存してエディタを終了した後、新しい環境変数を現在のセッションで有効にするには、シェル設定を再読み込みする必要があります。これは通常、次のように行います。
ソース〜/ .bashrc
すべてが正しく適用されているかを確認したい場合は、次のコマンドを使用します。 echo 変数について。LD_LIBRARY_PATH に現在含まれているパスが表示されます。
$LD_LIBRARY_PATH をエコーします
出力行に追加したディレクトリが含まれている場合、構成が正しく読み込まれ、ダイナミック ローダーがプログラムを起動するときにそのパスを考慮することを意味します。
何も壊さずにルートを追加する方法
多くの場合、LD_LIBRARY_PATH の内容を完全に置き換えるのではなく、既存のパスを保持したまま別のパスを追加したい場合があります。これは、他のライブラリが既に設定されていて、他のアプリケーションとの依存関係を壊したくない場合に重要です。
ルートを「連鎖」するには、通常、次のようなエクスポート形式が使用されます。 前の変数の前に新しいディレクトリを追加する例えば、 /home/osboxes/sample すでに定義されているものに対して、次のように記述することができます。 .bashrc:
エクスポート LD_LIBRARY_PATH=/home/osboxes/sample:${LD_LIBRARY_PATH}
順序が重要なのは、動的ローダーが最初に /home/osboxes/sample ディレクトリを検索し、次に変数が既に存在する他のディレクトリを検索するためです。これにより、特定のテストにのみ優先度の高いライブラリを含めることができ、その他の設定は変更せずに済みます。
ファイルを変更した後は、もう一度覚えておいてください 「source」コマンドを実行する オン ~/.bashrc 現在の端末に変更を適用し、再度確認するには echo $LD_LIBRARY_PATH 新しいルートがリストの一番上に表示されます。
それをお勧めします LD_LIBRARY_PATH の頻繁な変更を避ける不適切に実行された変更は、想像もつかないようなプログラムに影響を与える可能性があります。「add」パターンを以下の構文で使用してください。 ${LD_LIBRARY_PATH} 一貫性を保つのに役立ちますが、使いすぎないことが最善です。
図書館検索の仕組みとそれが危険な理由
LD_LIBRARY_PATH の背後には、ダイナミック ローダーの非常に特殊な動作があります。 検索優先順位この変数に入力したパスは、システム上のコンパイル済みパスや標準ディレクトリよりも先に処理されます。 /lib, /usr/lib o /usr/lib64.
問題は、これらの追加ディレクトリにシステムライブラリと同じ名前のライブラリが含まれているものの、バージョンが異なっていたり互換性がない場合に発生します。動的ローダーは、アプリケーションが元々別のバージョンにリンクされていたとしても、LD_LIBRARY_PATH 内で最初に見つかったライブラリを躊躇なく選択してしまいます。
この状況は、深刻なセキュリティ上の問題を含む、いくつかの種類の競合を引き起こす可能性があります。悪意のあるユーザーが、改ざんされたLD_LIBRARY_PATHを持つプログラムを実行させることに成功した場合、悪意のあるライブラリが紛れ込み、正規のバージョンを置き換えて、不要なコードを実行する可能性があります。
このため、setuid または setgid バイナリは通常、LD_LIBRARY_PATH を完全に無視します。これらのバイナリは管理者権限で実行されるため、ユーザー環境から任意のパスを受け入れることは大きなリスクとなります。システムはこのような場合、その変数を単純に破棄します。
安全以外にも、 パフォーマンスと効率 覚えておくべき点があります。LD_LIBRARY_PATHにディレクトリを追加すると、ローダーは実際には存在しないライブラリであっても、そのパスにあるライブラリを開こうとします。その結果、多くの呼び出しが失敗します。 open()これにより、「ENOENT (そのようなファイルまたはディレクトリはありません)」が返され、アプリケーションの起動が遅くなります。
パスを追加するほど、特にリモートディレクトリ(NFS)の場合は、プログラムの起動時間が長くなり、ファイルシステムへの負荷も大きくなります。数百人のユーザーがいる大規模環境では、LD_LIBRARY_PATH の過剰な使用が予期せぬボトルネックとなる可能性があります。
典型的な問題: 矛盾と隠れた依存関係
もう1つの非常に一般的な副作用は、バイナリとライブラリ間の不整合です。LD_LIBRARY_PATH によって、プログラムはリンクされたライブラリとは異なるバージョンのライブラリをロードするように強制されることがあり、それらは ABI レベルまたは動作レベルで常に 100% 互換性があるとは限りません。
互換性に明らかな問題がある場合、アプリケーションは起動に失敗したり、すぐにクラッシュしたりして、問題の痕跡がはっきりと残ります。しかし、本当に危険なのは、ライブラリが「ほぼ正常に動作する」ように見えても、その後、誤った結果を返したり、デバッグが困難なほど微妙に異なる動作をしたりする場合です。
特に問題となる使用例の一つは、LD_LIBRARY_PATHをユーザープロファイル、あるいはさらに悪いことにシステムプロファイルでグローバルに定義することです。こうなると、そのセッションで実行されているすべてのアプリケーションがその設定の影響を受けてしまい、追加パスに対応するように設計されていないアプリケーションでさえも影響を受けてしまいます。
これらのグローバルパスが変更されたり、存在しなくなったりすると、多くのバイナリが突然動作しなくなる可能性があります。なぜなら、誰も気づかないうちに、それらのバイナリはライブラリを見つけるためにLD_LIBRARY_PATHのその「パッチ」に依存するようになっていたからです。
このことから、多くの専門的な環境において、変数を長期的な安定した構成メカニズムとしてではなく、単発のテストツールまたは緊急時の解決策としてのみ使用することが重視される理由が説明できます。
実際に使用されているライブラリを確認する方法
変更がLD_LIBRARY_PATHにどのような影響を与えるかを完全に理解するには、次の点を知ることが重要です。 各実行ファイルがどのライブラリを使用しているかここで次のようなコマンドが使われます lddこれにより、動的リンクについてかなり明確な見解が得られます。
`ldd` コマンドは、指定されたバイナリに対して、どの動的ライブラリが必要としているか、またそれらがどのパスからロードされているかを表示します。たとえば、次のように実行します。
ldd /usr/bin/ファイル
次のような行のリストが表示されます。 libmagic.so.1 => /usr/lib64/libmagic.so.1の決議とともに linux-vdso.so.1, libc.so.6 そしてダイナミックチャージャー自体。この情報から 静止画 実行可能ファイルの主な依存関係。
ただし、共有ライブラリが 実行時に他のライブラリをロードする (例えば、 dlopen())であり、これらはlddの出力には反映されません。より完全な状況を把握するには、実行中のプロセスのアドレス空間に実際にマッピングされている.soファイルを調べる必要があります。
Solarisのようなシステムでは、プロセスIDに基づいてプロセスがロードしている動的ライブラリを一覧表示する`pldd`コマンドがあります。Bashのようなプログラムで使用すると、`ldd`で一覧表示されるライブラリに、文字変換モジュールやユーザーおよびグループ解決のためのNSSモジュールなどの他のライブラリがどのように追加されているかを確認できます。
純粋なLinuxでは、plddは常に標準バイナリとして利用できるわけではないが、 Perlや他のツールのスクリプトがある 情報を抽出する /proc/<PID>/maps同様の効果が得られます。これにより、LD_LIBRARY_PATH 設定によって予期しないライブラリがロードされていないかどうかを確認できます。
LD_LIBRARY_PATHへの依存を避けるためのよりクリーンな方法
LD_LIBRARY_PATH を使った回避策を積み重ねていく際の一般的な推奨事項はシンプルです。それは、できるだけ使用を控えることです。追加するパスはすべて、エラー、バージョン競合、パフォーマンスの問題の原因となる可能性があるため、より堅牢な代替手段を検討する価値があります。
アプリケーションをコンパイルする場合(例えば、『Linux From Scratch 』の手順に従ってコンパイルする場合)、リンカーの`-rpath`オプションを使用できます。このオプションを使用すると、実行ファイルが依存するライブラリへのパスを実行ファイルに直接埋め込むことができるため、バイナリはグローバル環境変数を変更することなく、ライブラリの場所を認識できます。
典型的な例は次のようになります。
cc -o myprog obj1.o … objn.o -Wl,-rpath=/path/to/lib -L/path/to/lib -lmylib
これにより、リンカーは /path/to/lib を実行ファイルの実行パスに設定する複数のルートが必要な場合は、環境変数を使用すると非常に便利です。 LD_RUN_PATHリンカーもこれを理解でき、コロンで区切られたディレクトリのリストを入力できます。
たとえば、次のことができます。
エクスポート LD_RUN_PATH=/path/to/lib1:/path/to/lib2:/path/to/lib3
cc -o myprog obj1.o … objn.o -L/path/to/lib1 -lmylib1 -L/path/to/lib2 -lmylib2
コンパイル後、次のように確認できます。 ldd バイナリ すべてのライブラリを正しく解決します LD_LIBRARY_PATH に依存しません。「見つかりません」というエラーが表示される場合は、Makefile と LD_RUN_PATH の設定を確認する必要があります。
再コンパイルできない場合は、chrpathなどのツールを使用して、実行ファイルに既に埋め込まれているランパスを変更できます。ただし、この手法には制限があります。既存の文字列を上書きすることはできますが、拡張することはできません。また、バイナリにランパスが定義されていない場合は、変更するものがありません。
ラッパースクリプトを使用してコマンドラインから特定の調整を行う
-rpath または chrpath を使用したリンクが利用できない場合でも、特定のアプリケーションのみを対象に LD_LIBRARY_PATH を調整するラッパースクリプトを使用できます。これは、ユーザープロファイルを直接変更するよりもはるかに影響の少ない方法です。
シェル内の典型的なラッパーは次のようになります。
#!/ bin / shを
LD_LIBRARY_PATH=/path/to/lib1:/path/to/lib2:/path/to/lib3
LD_LIBRARY_PATH をエクスポートする
exec /path/to/bin/myprog «$@»
この方法では、環境変数はmyprogとその子プロセスに対してのみ「汚染」され、セッション内で実行する他のコマンドには影響しません。特定のアプリケーションで特定のライブラリバージョンを使用せざるを得ない場合、これは完全に許容できる解決策です。
迅速なテストを行うためのもう一つの非常に便利な方法は、 `env`コマンドを使用して、単一の実行時のみ`LD_LIBRARY_PATH`を定義することです。例:
env LD_LIBRARY_PATH=/path/to/lib1:/path/to/lib2 ./myprog
このようにして変数は適用される その祈りにのみ de myprog完了すると、シェルはそのまま残り、次に実行するコマンドに影響を与える可能性のある奇妙なパスの痕跡は残りません。
次のようなことは絶対に避けてください。
エクスポート LD_LIBRARY_PATH=/path/to/lib1:/path/to/lib2
./myprog
このパターンはLD_LIBRARY_PATHを残します 以降のすべての注文に対して定義されます ターミナルから起動すると、後から追跡するのが非常に困難な副作用を引き起こす可能性があります。独立したテストの場合、 env ずっときれいになりました。
避けるべき良い習慣とよくある間違い
広く受け入れられている黄金律の推奨事項は ログインプロファイルでLD_LIBRARY_PATHを定義しないでくださいユーザーファイルにもシステムファイルにも追加しないでください。つまり、次のようなファイルには追加しないでください。 ~/.bash_profile, ~/.profile, /etc/profile または類似。
このような機密性の高い変数をグローバルに設定すると、そのユーザーが起動するすべてのアプリケーションが、システムライブラリとの連携に完全に設定されているアプリケーションであっても、これらの追加パスを使用するようになります。特定のスクリプトや単発の実行にのみ適用範囲を限定する方が、はるかに安全な方法です。
インストール中にLD_LIBRARY_PATHをプロファイルに追加するよう要求したり、グローバルに自動的に追加したりするサードパーティ製インストーラーには注意が必要です。ほとんどの場合、これはプロバイダーにとっては手軽な方法ですが、中期的には環境に問題を引き起こす可能性があります。
可能な限り、少し努力してクリーンな代替手段を探す価値があります。例えば、実行ファイルの実行パスを調整したり、ライブラリを標準ディレクトリにインストールしたり、最新のパッケージングメカニズムを使用したり、一般的な環境を変更する代わりにスクリプトラッパーでアプリケーションをラップしたりすることです。
変数を使用せざるを得ない場合は、パスをできるだけ簡潔かつ具体的にし、ディレクトリの数を最小限に抑え、厳密に必要な場合を除き、リモートファイルシステム上のパスは絶対に避けてください。
こうした点を踏まえると、LD_LIBRARY_PATH は強力ではあるものの、扱いが難しいツールであることに変わりはありません。新しいライブラリバージョンのテスト、古い .so ファイルの再配置、大規模アプリケーション用の自己完結型環境の構築などには非常に便利ですが、無差別に使用すると、セキュリティリスク、パフォーマンスの問題、デバッグが困難な不整合などを引き起こす可能性があります。動的ローダーの仕組みを理解し、-rpath、LD_RUN_PATH、ラッパースクリプトなどの代替手段を利用し、この変数を特定の状況に限定することが、LD_LIBRARY_PATH をシステムにとっての落とし穴にすることなく、その利点を最大限に活用するための最善の方法です。