Puppeteer在Cpanel VPS上从控制台运行正常,但通过PHP调用时失败
看起来你遇到的是典型的Web服务器用户权限/环境隔离问题——控制台运行时的环境变量、资源权限和Apache(Cpanel专属用户)调用时的环境差异极大,我给你几个针对性的排查和解决方向,按顺序试:
1. 先搞清楚Web运行用户的真实环境
你已经发现是Cpanel创建的专属用户(不是nobody),哪怕给了shell权限,网页调用时的环境和你手动登录控制台的环境也完全不一样。先写个PHP测试脚本摸清楚底:
<?php echo "当前运行用户: " . get_current_user() . "\n"; echo "环境变量PATH: " . getenv('PATH') . "\n"; echo "Chromium是否可执行: \n"; echo shell_exec('/usr/bin/chromium-browser --version 2>&1') . "\n"; echo "Node.js是否可执行: \n"; echo shell_exec('/usr/bin/node --version 2>&1') . "\n";
对比你在控制台用该Cpanel用户登录后执行echo $PATH、chromium-browser --version的输出,大概率是Web用户的PATH里没有Node或Chromium的路径,或者根本没有权限执行这些二进制文件。
2. 给Puppeteer补全关键启动参数+指定全局Chromium路径
你已经装了全局Chromium,直接指定它的绝对路径,同时补上几个解决无头模式权限/资源问题的参数:
修改你的Node.js脚本:
const browser = await puppeteer.launch({ headless: true, args: [ '--no-sandbox', '--disable-gpu', '--disable-dev-shm-usage', // 解决VPS共享内存不足的常见问题 '--single-process', // 减少多进程带来的权限隔离问题 '--no-zygote' // 避免Chromium的zygote进程权限限制 ], executablePath: '/usr/bin/chromium-browser' // 用which chromium-browser确认路径是否正确 });
3. 给Web用户补全所有必要的权限
Cpanel的用户对网站目录外的文件默认有严格限制,你之前用setfacl的思路是对的,但要针对实际的Cpanel用户(不是nobody)来设置:
假设你的Cpanel用户是mycpaneluser,执行:
# 给Puppeteer自带的Chromium目录加权限 sudo setfacl -R -m u:mycpaneluser:rX /path/to/your/node_modules/puppeteer/.local-chromium/ # 给全局Chromium加权限 sudo setfacl -R -m u:mycpaneluser:rX /usr/bin/chromium-browser # 确保你的项目目录对该用户可读写 chown -R mycpaneluser:mycpaneluser /path/to/your/project/
4. 检查Cpanel的PHP安全限制
有些Cpanel配置会默认限制shell_exec或者执行外部命令:
- 打开Cpanel的「MultiPHP INI编辑器」,看
disable_functions里有没有shell_exec,如果有就临时去掉测试; - 检查
open_basedir设置,如果有,确保Node.js和Chromium的路径在允许范围内,或者临时关闭验证。
5. 终极招:强制切换到Cpanel用户执行
如果以上都不行,直接在shell_exec里用su切换到目标用户执行脚本(注意用绝对路径):
$html = shell_exec("su - mycpaneluser -c 'node /full/absolute/path/to/pdf.js $url' 2>&1");
这个方法能绕开Apache的环境隔离,但要确保系统允许Apache用户切换(实在没办法再用,尽量优先前面的方案)。
我之前在Cpanel VPS上遇到过几乎一模一样的问题,最后发现是Web用户的PATH里没有Node.js路径,加上--disable-dev-shm-usage参数就解决了,你按顺序试应该能搞定。
备注:内容来源于stack exchange,提问作者valepu

