PHP调用Google Lighthouse报错:Cannot read properties of undefined (reading 'split')
问题
已安装Google Lighthouse用于网站测速,在用户zak身份下可正常运行,但通过PHP脚本以www-data身份调用时,出现错误:npm ERR! Cannot read properties of undefined (reading 'split')。
PHP脚本内容
<?php if ( empty( $_POST['website'] ) ){ die('Invalid Website'); } echo shell_exec("whoami") . "<br />"; $website = $_POST['website']; $test = shell_exec("npx lighthouse $website --chrome-flags='--headless' 2>&1"); echo "Test result for $website:<br />$test";
已验证的测试项
- 以
zak身份在命令行执行npx lighthouse http://example.com --chrome-flags='--headless' 2>&1可正常运行; - 通过bash脚本验证
www-data可访问node、npm、npx; sudo -u www-data在命令行执行该Lighthouse命令也正常。
错误根源
查看详细日志发现,错误源于/usr/local/lib/node_modules/npm/node_modules/libnpmexec/lib/index.js中的代码:
const PATH = ( process.env.PATH || process.env.Path || process.env.path ).split(delimiter) // <- ERROR
代码尝试对未定义的PATH环境变量执行split操作,触发报错。
疑问
为何PHP脚本中无法运行该命令?是否需要特殊权限?能否进行进一步排查?这是否是Lighthouse的bug?
原因与解决方案
核心原因:PHP执行shell命令时环境变量PATH缺失
PHP通过shell_exec调用系统命令时,属于非交互式无登录shell,不会加载www-data用户的shell配置文件(如.bashrc、.profile),导致环境变量PATH为空或不包含node/npm的安装路径。而命令行下sudo -u www-data属于交互式登录shell,会加载配置文件,因此能正常运行。
解决方法
在命令中显式指定PATH
修改PHP中的shell_exec命令,先设置PATH再执行npx:$test = shell_exec("export PATH=/usr/local/bin:$PATH && npx lighthouse $website --chrome-flags='--headless' 2>&1");(注:
/usr/local/bin替换为你的node/npm实际安装路径,可通过which npm命令查看)在PHP脚本中全局设置环境变量
在脚本开头添加:putenv("PATH=/usr/local/bin:" . getenv("PATH"));确保后续执行的shell命令能获取到正确的PATH。
修改PHP全局配置
编辑PHP-FPM的配置文件(如/etc/php/[你的PHP版本]/fpm/pool.d/www.conf),添加:env[PATH] = /usr/local/bin:/usr/bin:/bin重启PHP-FPM服务后,所有PHP脚本执行时都会带上正确的PATH环境变量。
进一步排查步骤
- 查看PHP执行时的环境变量:在脚本中添加
echo shell_exec("printenv");,检查输出的PATH是否包含node/npm的路径; - 直接测试node访问性:执行
shell_exec("node -v 2>&1"),确认node是否能被PHP调用; - 使用绝对路径执行npx:用
/usr/local/bin/npx替换命令中的npx,绕过PATH依赖; - 检查系统安全限制:如果是Linux系统,排查SELinux或AppArmor是否阻止PHP调用外部命令,可临时关闭测试(生产环境需谨慎)。
是否为Lighthouse的bug?
不是。该错误是npm的libnpmexec库未做严格空值判断导致,但本质是PHP执行时环境变量缺失的问题——正常情况下PATH至少包含系统默认路径,只有在极端缺失场景下才会触发。Lighthouse本身无问题,因为命令行下www-data能正常运行。
内容的提问来源于stack exchange,提问作者Zak

