概要

本番サーバの環境変数ファイルに LD_LIBRARY_PATHPKG_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/libld.so.conf 系に含まれている。

  • Debian/Ubuntu: /etc/ld.so.conf.d/libc.conf/usr/local/lib が入っている
  • RHEL 系: 同様に標準で入っていることが多い

したがって、LD_LIBRARY_PATH=/usr/local/lib:/usr/local/lib64必要になっている時点で、以下のいずれかを疑うべき。

  1. ldconfig を実行していない
  2. /etc/ld.so.conf.d/ に配置していない
  3. そもそもライブラリが /usr/local/lib64 に入れるべきでない場所に置かれている

PKG_CONFIG_PATH は本番に存在すべきでない

PKG_CONFIG_PATHpkg-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 未実行や配置ミスなど、別の問題を疑うべき