我也一直在努力寻找 Mac OS X 上 "PHP Warning: oci_new_connect(): OCIEnvNlsCreate() failed. There is something wrong with your system - please check that DYLD_LIBRARY_PATH includes the directory with Oracle Instant Client libraries" 错误的解决方案。最后经过大量研究,我找到了一个可持续修复此错误的解决方案,并希望在这里分享以帮助其他人.
作为一点背景知识,我在 OS X 10.8.4 上使用 Apple 提供的 PHP 安装(带有 Suhosin-Patch 的 PHP 5.3.15),并在我下载后使用 PECL 存储库安装 OCI8 扩展从 Oracle.com 下载 Oracle Instant Client。
我还测试了我能在网上找到的所有解决此错误的方法,包括在我的~/.bash_profile 和~/.bashrc 文件中设置DYLD_LIBRARY_PATH、ORACLE_HOME 和LD_LIBRARY_PATH 系统环境变量;尝试通过 Apache 的 mod_env 模块和 httpd.conf 中的 SetEnv 配置环境变量;在 PHP 代码中通过putenv("DYLD_LIBRARY_PATH=/...") 设置环境变量;以及其他建议,但都未能解决错误。
我过去发现的唯一可行的解决方案是我在以前的 OS X 10.7.8 安装中使用的,它涉及将 Oracle Instant Client 库的内容复制到始终搜索但隐藏的系统文件夹:/usr/include 、/usr/bin 和 /usr/lib。但是,我觉得这个解决方案并不理想,并且可能会导致长期维护和升级库变得困难,我觉得这个问题的可持续解决方案必须存在于某个地方。
最后,经过大量额外研究,我偶然发现了 OpenSUSE 论坛上的一篇帖子,其中详细介绍了那里的一组用户如何在 OpenSUSE 上解决 Apache/PHP 下的相同 OCI 错误。该论坛帖子还扩展了我在其他论坛帖子中看到的 cmets,这些帖子谈到了在典型的 Apache/PHP 设置中存在多种类型的“环境变量”:
- 有 Apache 环境变量,通常通过
mod_env 配置 - 这些出现在 php_info() 页面的 Apache Environment 部分。
- 有 PHP 环境变量,通常通过
php.ini 或 putenv() 设置,并且可以通过 getenv() 和类似方法在您的脚本中访问。
- 最后,我在这里所说的“特定于进程的环境变量”——这些是必须在启动 Apache 进程之前配置的环境变量,并且是 Apache 启动进程本身的一部分。例如,在
~/.bash_profile 中指定这些环境变量是不够的。这些特殊的环境变量在 Apache 进程启动时由其所有子进程(包括 Apache 进程的其他衍生品)和 PHP 本身继承,而且至关重要的是 - 正是这些非常“特定于进程的环境”我们需要配置的变量,以便永久且可持续地解决 OCI8 库的问题。正确配置后,这些环境变量将出现在php_info() 页面的Environment Variables 部分。
导致我在 Mac OS X 上找到解决方案的线索来自 OpenSUSE forum 上的帖子,其中包括论坛成员 key_nap 的评论,他注意到启动 Apache 进程时在 OpenSUSE 上,还加载了一个特殊的配置文件。这个文件/usr/share/apache2/load_configuration原来是一个bash脚本,他们想到他们可以在这个bash脚本中包含相关的export DYLD_LIBRARY_PATH=...语句,并且通过在那里配置环境变量,它们将被启动时的 Apache 进程及其子进程。
这让我想知道,在 Mac OS X 上,我们可以在哪里正确配置这些相同的“特定于进程的环境变量”。由于launchd 几乎只在OS X 上用于处理系统进程的加载,我想知道我们是否能够在Apache 的launchd 配置文件中配置必要的环境变量?在 OS X 10.8 上,您应该在 /System/Library/LaunchDaemons/org.apache.httpd.plist 找到 Apache 的 launchd 配置 .plist 文件。当我在系统上打开文件时,我立即注意到指定环境变量的部分!
因此,我们的解决方案(经测试可在 Mac OS X 10.8.4 上运行)是编辑 org.apache.httpd.plist 文件,如下所示(注意将 ORACLE_HOME、DYLD_LIBRARY_PATH 和 LD_LIBRARY_PATH 包含到 EnvironmentVariables部分),然后通过从终端运行 sudo apachectl restart 重新启动 Apache。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Disabled</key>
<true/>
<key>Label</key>
<string>org.apache.httpd</string>
<key>EnvironmentVariables</key>
<dict>
<key>XPC_SERVICES_UNAVAILABLE</key>
<string>1</string>
<key>ORACLE_HOME</key>
<string>/Users/workstation/Oracle</string>
<key>DYLD_LIBRARY_PATH</key>
<string>/Users/workstation/Oracle/lib</string>
<key>LD_LIBRARY_PATH</key>
<string>/Users/workstation/Oracle/lib</string>
</dict>
<key>ProgramArguments</key>
<array>
<string>/usr/sbin/httpd-wrapper</string>
<string>-D</string>
<string>FOREGROUND</string>
</array>
<key>OnDemand</key>
<false/>
<key>SHAuthorizationRight</key>
<string>system.preferences</string>
</dict>
</plist>
通过将这些“进程特定环境变量”定义添加到 Apache launchd 配置文件中,我们确保这些环境变量被 Apache 及其所有子进程正确继承,其中包括 PHP 和 PHP 加载的任何模块,例如 OCI8 !您显然应该将上面示例中显示的路径 /Users/workstation/Oracle/... 替换为您自己的 Oracle 客户端库安装的正确路径——使用与在 ~/.bash_profile 中指定这些环境变量时相同的值。
还要确保为您的系统安装了正确版本的 Oracle Instant Client Libraries - 即 32 位或 64 位变体,具体取决于您运行的 OS X 版本以及是否使用 Apache 和 PHP以 32 位或 64 位模式运行。在 OS X 10.8 及更高版本上,Apache/PHP 应该作为 64 位进程运行。如果您不确定,您可以像我在以前的 Mac 上所做的那样,使用 XCode 中的 lipo 工具将 32 位和 64 位版本的 Oracle Instant Client 库二进制文件组合成单个多架构胖二进制文件,该工具将创建可在任一平台上加载的二进制文件。
最后,上面详述的在 Apache 的 launchd 配置文件中配置环境变量的解决方案也应该可以解决通过 Apache 运行的其他 PHP 模块中的类似错误,这些模块依赖于环境变量来查找其链接库。如果从命令行运行 PHP,您应该能够在 ~/.bash_profile 和/或 ~/.bashrc 文件中指定所需的所有环境变量。