2013年1月13日日曜日

libclntsh.so.11.1が見つからない。


PHPからoci8が連携できずに2日ほどハマったのでメモ。
Oracle関連って保守契約か何だかの約束で公式回答を
ブログやらニュースサイトに記載してはいけないということらしいが、
本件については明確に保守担当からPHPの連携およびOSに関わる部分なので
Oracle対応対象外ですと言ってもらった(見捨てられた)ので問題ないだろう。

まず、Oracleクライアントをランタイムでインストールし、
そして、PHPを--with-oci8=shared,$ORACLE_HOMEオプションをつけてコンパイルした。
正常にoci8.soライブラリが作成されたことを確認し、php.iniに追加してやる。

今回、PHPはCGI経由で呼び出すのでphp-cgiをCGIディレクティブにリンクし、
phpinfoだけ書いたindex.phpを作成し、稼働確認。
コマンドラインでphp-cgi -i index.phpでは正常に稼働し、oci8もenableだった。
ところが、ブラウザからアクセスするとphpinfoは表示されるもののoci8関連の項目がない。
error_logを確認すると、案の定下記のエラーが。。。

libclntsh.so.11.1: cannot open shared object file: No such file or directory

なるほど、Apacheの実行ユーザがライブラリパスを認識できないのね、と考え、
$ORACLE_HOME/libをld.so.confに追加したら
今度はlibexpat.so.11.1 is not a symbolic linkというエラーが出る。
もちろん、ブラウザ接続でのoci8認識はできず。

ここで保守担当に連絡を取るも、それってPHPのエラーですやん、という回答。
確かにその通り、じゃぁ、ld.so.confについてはと聞くとそれはOSですやん、と宣った。

仕方がないので、自力で対応することに。。。

まず、PHPの公式マニュアルに従ってLD_LIBRARY_PATHを認識させる方法を試す。
ところが、/etc/sysconfig/httpdとenvvarsではPHPまで届かない。。
最終手段でSetEnvしたところ、やっとPHPまでLD_LIBRARY_PATHが環境変数として渡った。
しかし、libclntsh.soのエラーは変わらずブラウザではPHPからoci8が起動できない。

それからググって出てきたことはひと通り試す。

Apache起動スクリプトに「export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/foo/var/hoge.so」
と書いてもダメ。
libclntsh.so.11.1をoci8.soと同じ所に置いてもダメ、
静的にコンパイルしても動的にコンパイルしても変わらず、
LD_LIBRARY_PATHのディレクトリのパーミッションをゆるめてもダメ、
Apache起動ユーザーのセカンドグループにoinstallを追加してもダメ、
LoadFileでlibclntsh.soを直接指定してもダメ。

とうとう万策尽きて、怒りのApache起動ユーザをnologinからbashにして無理やりスイッチ、
ldd oci8.soしたら、libclntsh.soが「not found」となっていて「ん?」
他にもrootで実行するlddと出力結果が違う。。

そこでやっとわかる。
今回、Oracleクライアントのインストール先をデフォルトに従って/home/oracleの下にした。
そのため、上位のフォルダの制限が強すぎてLD_LIBRARY_PATHが認識できなかったらしい。

対応としてOracleクライアントのインストール先を/optに変更したところ、
やっとブラウザからもoci8を認識するようになった。