LD_LIBRARY_PATH と PKG_CONFIG_PATH を本番 .env に書くべきでない理由
概要
本番サーバの環境変数ファイルに LD_LIBRARY_PATH と PKG_CONFIG_PATH が追加されているのを見つけて違和感を覚えた。これらは本来、本番実行環境に書くべきものではない。記録としてまとめる。
発端
リポジトリで管理されている environment.repo と、実サーバ上の environment.server を diff したところ、サーバ側にだけ以下の行が追加されていた。
+ LD_LIBRARY_PATH=/usr/local/lib:/usr/local/lib64:$LD_LIBRARY_PATH
+ PKG_CONFIG_PATH=/usr/local/lib/pkgconfig:/usr/local/lib64/pkgconfig:$PKG_CONFIG_PATH
LD_LIBRARY_PATH はデバッグ用
man ld.so にも明記されているとおり、LD_LIBRARY_PATH は主にデバッグ用、あるいは新しいライブラリを一時的に差し替えるための仕組みであり、本番の恒久設定として使うものではない。
本番でこれを設定する必要があるということは、バイナリに RPATH/RUNPATH が埋め込まれていないか、システムのローダ設定(/etc/ld.so.conf)が整っていないことを意味する。
あるべき対処の優先順位
表1: ライブラリパス解決の正しい方法
| 優先 | 方法 | 用途 |
|---|---|---|
| 1 | ビルド時に -Wl,-rpath=/path or LD_RUN_PATH で RPATH を埋め込む |
配布物として最もクリーン |
| 2 | /etc/ld.so.conf.d/xxx.conf に書いて ldconfig |
システム全体に恒久適用 |
| 3 | LD_LIBRARY_PATH |
最後の手段(デバッグ・一時回避) |
Linux でも ELF の DT_RPATH / DT_RUNPATH の仕組みは Solaris と本質的に同じで、ビルド時に RPATH を埋め込めばローダが自動的に見つけてくれる。
/usr/local/lib が必要な時点で怪しい
多くの Linux ディストリでは、デフォルトで /usr/local/lib は ld.so.conf 系に含まれている。
- Debian/Ubuntu:
/etc/ld.so.conf.d/libc.confに/usr/local/libが入っている - RHEL 系: 同様に標準で入っていることが多い
したがって、LD_LIBRARY_PATH=/usr/local/lib:/usr/local/lib64 が必要になっている時点で、以下のいずれかを疑うべき。
ldconfigを実行していない/etc/ld.so.conf.d/に配置していない- そもそもライブラリが
/usr/local/lib64に入れるべきでない場所に置かれている
PKG_CONFIG_PATH は本番に存在すべきでない
PKG_CONFIG_PATH は pkg-config が .pc ファイルを探すための変数で、コンパイル/リンク時にしか使わない。本番のアプリケーションプロセス起動時には無関係。
表2: 2 つの変数の用途の違い
| 変数 | 用途 | 有効なタイミング |
|---|---|---|
PKG_CONFIG_PATH |
.pc ファイルの検索パス |
ビルド時のみ |
LD_LIBRARY_PATH |
実行時ローダのライブラリ検索パス | 実行時 |
これが本番 env に書かれているのは、本番サーバ上で native extension のビルドを行う運用で、そのときに必要だから残している、というケースが多い。ビルド環境と実行環境が分離されていない兆候とも言える。
何が起きているかの推測
/usr/local/lib{,64} に手動ビルドの libxxx を入れている
↓
そのままだとアプリ(gem の native ext 等)から見つからない
↓
LD_LIBRARY_PATH で通してとりあえず動かした
↓
ビルド時に .pc も要るので PKG_CONFIG_PATH も足した
↓
.env に残り続ける
対症療法で蓋をしているが、根本は「/usr/local/lib{,64} への手動インストール運用」と「ビルド環境と実行環境の未分離」にある。
あるべき姿
表3: 本来の配置先
| 項目 | あるべき場所 |
|---|---|
LD_LIBRARY_PATH |
削除し、/etc/ld.so.conf.d/*.conf + ldconfig、または RPATH 埋め込み |
PKG_CONFIG_PATH |
本番 env から削除、ビルド環境のみに限定 |
まとめ
LD_LIBRARY_PATHは本番の恒久設定に使うものではない。ビルド時の RPATH 埋め込みかld.so.conf.d+ldconfigで解決するPKG_CONFIG_PATHはビルド時専用。本番実行 env に存在する時点で、ビルドと実行の分離ができていない/usr/local/libの解決にLD_LIBRARY_PATHが必要になった時点で、ldconfig未実行や配置ミスなど、別の問題を疑うべき