瘦子
我将 PHP 构建为 apache 模块 (libphp56.so),并将其链接到 MacPorts 的 libcurl。但是,如果加载了 libphp56.so,httpd 在启动(通过 launchd)时会失败,并打印库版本不匹配错误。
脂肪
我运行 PHP 的配置脚本,--with-curl=/opt/local
将其与 /opt/local/lib/libcurl.4.dylib (由 MacPorts 提供)链接。 libcurl 的副本是版本 9.0.0,但 dyld 声称正在加载版本 7.0.0,这恰好是 /usr/lib/libcurl.4.dylib 的版本。目前,我假设后者正在加载。
apachectl
调用launchctl
运行 httpd。如果直接运行,httpd会加载libphp56.so并且运行不会出错。
以下是来自命令行的一些相关信息(为了可读性添加了空格):
$ sudo -s #apachectl 配置测试 httpd:/private/etc/apache2/httpd.conf 第 174 行存在语法错误: 无法将 libexec/apache2/libphp56.so 加载到服务器中: dlopen(/库/WebServer/libexec/apache2/libphp56.so,10): 库未加载:/opt/local/lib/libcurl.4.dylib 引用自:/Library/WebServer/libexec/apache2/libphp56.so 原因:库版本不兼容:libphp56.so需要9.0.0或更高版本,但libcurl.4.dylib提供7.0.0版本 # /usr/sbin/httpd # ps -ax -O gid | grep /usr/sbin/httpd 6878 0 ?? SS 0:00.22 /usr/sbin/httpd 6901 70 ?? S 0:00.00 /usr/sbin/httpd 6907 0 s008 S+ 0:00.00 grep --color=auto /usr/sbin/httpd # 杀死-术语 6878 # otool -L /opt/local/lib/libcurl.4.dylib | grep libcurl 函数 /opt/local/lib/libcurl.4.dylib: /opt/local/lib/libcurl.4.dylib(兼容版本9.0.0,当前版本9.0.0) # otool -L /usr/lib/libcurl.4.dylib | grep libcurl 函数 /usr/lib/libcurl.4.dylib: /usr/lib/libcurl.4.dylib(兼容版本7.0.0,当前版本8.0.0) # otool -L /Library/WebServer/libexec/apache2/libphp56.so | grep libcurl 函数 /opt/local/lib/libcurl.4.dylib(兼容版本9.0.0,当前版本9.0.0) # 回显“x${DYLD_LIBRARY_PATH}x” xx # grep -r 'DYLD_.*_PATH' /etc # launchctl getenv DYLD_LIBRARY_PATH
httpd 的 launchd.plist 相当基本:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Disabled</key>
<false/>
<key>EnvironmentVariables</key>
<dict>
<key>XPC_SERVICES_UNAVAILABLE</key>
<string>1</string>
</dict>
<key>KeepAlive</key>
<dict>
<key>SuccessfulExit</key>
<false/>
</dict>
<key>Label</key>
<string>org.apache.httpd</string>
<key>ProgramArguments</key>
<array>
<string>/usr/sbin/httpd</string>
<string>-D</string>
<string>FOREGROUND</string>
</array>
</dict>
</plist>
设置迪尔德报告环境变量DYLD_PRINT_TO_FILE
,DYLD_PRINT_ENV
并DYLD_PRINT_LIBRARIES
显示 launchd 设置 DYLD_LIBRARY_PATH 并加载 /usr/lib/libcurl.4.dylib。
# DYLD_PRINT_TO_FILE=~/httpd.log DYLD_PRINT_ENV=1 DYLD_PRINT_LIBRARIES=1 apachectl configtest # grep -P 'curl|DYLD_' ~/httpd.log DYLD_PRINT_TO_FILE=/Users/Capra/httpd.log DYLD_PRINT_LIBRARIES=1 DYLD_PRINT_ENV=1 DYLD_PRINT_LIBRARIES=1 DYLD_PRINT_TO_FILE=/Users/Capra/httpd.log DYLD_LIBRARY_PATH=/usr/lib DYLD_PRINT_ENV=1 dyld:已加载:/usr/lib/libcurl.4.dylib # 回显 > ~/http.log # DYLD_PRINT_TO_FILE=~/httpd.log DYLD_PRINT_ENV=1 DYLD_PRINT_LIBRARIES=1 /usr/sbin/httpd -D FOREGROUND ^C # grep -P 'curl|DYLD_' ~/httpd.log DYLD_PRINT_TO_FILE=/Users/Capra/httpd.log DYLD_PRINT_LIBRARIES=1 DYLD_PRINT_ENV=1 dyld:已加载:/opt/local/lib/libcurl.4.dylib dyld:已卸载:/opt/local/lib/libcurl.4.dylib dyld:已加载:/opt/local/lib/libcurl.4.dylib
请注意,libcurl 并不是唯一遇到此问题的库。在进行故障排除时,我在构建过程中遗漏了 PHP 的curl 扩展,并收到了有关 libxml 的类似消息。
问题
DYLD_LIBRARY_PATH
通过 launchd 运行时如何取消httpd 的设置?安全后果是什么?
尝试的解决方案
- launchctl unsetenv DYLD_LIBRARY_PATH
DYLD_LIBRARY_PATH
在 org.apache.httpd.plist 中设置。- 让 org.apache.httpd.plist 为 httpd 运行一个包装器来设置
DYLD_LIBRARY_PATH
非解决方案
虽然我可以链接到系统 libcurl,但我正在寻找一种让 PHP 使用更新的组件运行的方法;链接 /usr/lib/libcurl.4.dylib 只是最后的手段。完全避免 launchd、不在构建中包含受影响的 PHP 扩展/库以及替换系统 libcurl 也被认为是非解决方案。我几乎会考虑有一个可以移动的包装纸。
系统信息
- 操作系统:Mac OS X 10.10.5 优胜美地。
- 网络服务器:Apache 2.4.16
- PHP 5.6.31