PHP执行Node命令返回状态码1的问题求助
PHP exec执行带LD_PRELOAD的Node命令失败(retval=1)
问题描述
在PHP 7.3 + Nginx + Ubuntu 22.04环境下,执行以下PHP代码调用Node脚本生成SVG文件:
$cmd = 'LD_PRELOAD="/var/www/localhost/node/so/libcrypto.so.0.9.8 /var/www/localhost/node/so/libssl.so.0.9.8" /var/www/localhost/node/node /var/www/localhost/node/nodejs-highcharts.js /tmp/201c0374305c6a74d019739c0f519a9d'; $output = exec($cmd, $out, $retval); file_put_contents('/tmp/output.txt', 'output: [' . print_r($output, true) . "]\n\nout: [" . print_r($out, true) . "]\n\nretval: [" . print_r($retval, true) . "]\n\ncmd: [" . $cmd . ']');
直接在命令行执行该命令可正常生成SVG文件,但通过PHP执行时返回结果为空,retval=1,且Node脚本首行的文件写入操作未执行,输出如下:
output: [] out: [Array ( ) ] retval: [1] cmd: [LD_PRELOAD="/var/www/localhost/node/so/libcrypto.so.0.9.8 /var/www/localhost/node/node /var/www/localhost/node/nodejs-highcharts.js /tmp/74d8fe466d722be67ef78c606c3e5d37]
已完成排查:
- 将node目录下所有文件的用户改为www-data,权限设为775,Nginx以www-data用户运行;
- 未触发PHP错误;
- 不清楚状态码1的具体含义。
可能的原因及解决方法
1. 状态码1的含义
retval=1通常表示命令执行过程中发生一般性错误(如参数错误、依赖缺失、隐性权限问题),但默认情况下exec只捕获标准输出(stdout),错误输出(stderr)会被丢弃,这是无法看到具体错误的核心原因。
2. 捕获错误输出排查问题
修改PHP中的命令,将stderr重定向到stdout,这样就能在$out中看到具体错误信息:
$cmd = 'LD_PRELOAD="/var/www/localhost/node/so/libcrypto.so.0.9.8 /var/www/localhost/node/so/libssl.so.0.9.8" /var/www/localhost/node/node /var/www/localhost/node/nodejs-highcharts.js /tmp/201c0374305c6a74d019739c0f519a9d 2>&1'; $output = exec($cmd, $out, $retval); file_put_contents('/tmp/output.txt', 'output: [' . print_r($output, true) . "]\n\nout: [" . print_r($out, true) . "]\n\nretval: [" . print_r($retval, true) . "]\n\ncmd: [" . $cmd . ']');
执行后查看/tmp/output.txt,即可获取具体错误提示(如动态库加载失败、Node依赖缺失等)。
3. LD_PRELOAD路径与权限问题
- 确认
libcrypto.so.0.9.8和libssl.so.0.9.8本身的权限:需确保这两个so文件的所有者为www-data,权限至少为644(可读); - Ubuntu 22.04默认启用
security/ld.so安全限制,www-data用户可能被限制加载自定义动态库。可尝试在命令前添加env命令,确保环境变量生效:
env LD_PRELOAD="/var/www/localhost/node/so/libcrypto.so.0.9.8 /var/www/localhost/node/so/libssl.so.0.9.8" /var/www/localhost/node/node /var/www/localhost/node/nodejs-highcharts.js /tmp/201c0374305c6a74d019739c0f519a9d
将该命令替换到PHP的$cmd中重新测试。
4. PHP执行环境的环境变量差异
命令行用户与www-data(PHP-FPM/Nginx)的环境变量不同,可能导致Node找不到依赖。可在命令前显式设置必要的环境变量:
$cmd = 'PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" LD_PRELOAD="/var/www/localhost/node/so/libcrypto.so.0.9.8 /var/www/localhost/node/so/libssl.so.0.9.8" /var/www/localhost/node/node /var/www/localhost/node/nodejs-highcharts.js /tmp/201c0374305c6a74d019739c0f519a9d 2>&1';
5. 验证www-data用户的执行权限
直接切换到www-data用户执行命令,模拟PHP的执行环境:
sudo su - www-data -s /bin/bash # 执行目标命令 LD_PRELOAD="/var/www/localhost/node/so/libcrypto.so.0.9.8 /var/www/localhost/node/so/libssl.so.0.9.8" /var/www/localhost/node/node /var/www/localhost/node/nodejs-highcharts.js /tmp/201c0374305c6a74d019739c0f519a9d
如果此处执行失败,可直接看到错误并针对性解决;如果执行成功,需排查PHP的exec调用是否存在其他限制(如disable_functions禁用exec、open_basedir路径限制等)。
内容的提问来源于stack exchange,提问作者raphael75
相关产品推荐
相关产品推荐

