CentOS7下从PHP调用Puppeteer脚本,浏览器访问失败求助
CentOS7下PHP通过浏览器调用Puppeteer报错EACCES的原因及解决办法
问题描述
我在CentOS 7上安装了Puppeteer,直接运行node test.js能正常生成PNG图片。写了PHP脚本用shell_exec调用这个Node.js脚本,命令行执行php test.php也能正常生成PNG,但通过浏览器访问该PHP脚本(比如http://192.168.0.55/puppeteer/test.php)时无法生成PNG,报错EACCES:无法连接127.0.0.1:33060。
Node.js 脚本
const puppeteer = require('puppeteer'); async function runTest() { try { const browser = await puppeteer.launch({ executablePath: '/usr/bin/chromium-browser', headless: true, args: ['--no-sandbox'], }); const page = await browser.newPage(); await page.goto('https://www.google.com.tw'); await page.screenshot({path: 'example2.png'}); await browser.close(); } catch (error) { console.error('Error:', error); } } runTest();
PHP 脚本
$command = 'node test.js'; shell_exec($command .' 2>&1');
报错详情
Error: ErrorEvent { [Symbol(kTarget)]: WebSocket { _events: [Object: null prototype] { open: [Function], error: [Function] }, _eventsCount: 2, _maxListeners: undefined, _binaryType: 'nodebuffer', _closeCode: 1006, _closeFrameReceived: false, _closeFrameSent: false, _closeMessage: <Buffer >, _closeTimer: null, _extensions: {}, _paused: false, _protocol: '', _readyState: 3, _receiver: null, _sender: null, _socket: null, _bufferedAmount: 0, _isServer: false, _redirects: 0, _url: 'ws://127.0.0.1:33060/devtools/browser/c9968cc9-8411-4558-a50a-8d3fbe4ffc22', _originalIpc: false, _originalSecure: false, _originalHostOrSocketPath: '127.0.0.1:33060', _req: null, [Symbol(kCapture)]: false }, [Symbol(kType)]: 'error', [Symbol(kError)]: Error: connect EACCES 127.0.0.1:33060 - Local (0.0.0.0:0) at internalConnect (node:net:1041:16) at defaultTriggerAsyncIdScope (node:internal/async_hooks:464:18) at node:net:1134:9 at processTicksAndRejections (node:internal/process/task_queues:78:11) { errno: -13, code: 'EACCES', syscall: 'connect', address: '127.0.0.1', port: 33060 }, [Symbol(kMessage)]: 'connect EACCES 127.0.0.1:33060 - Local (0.0.0.0:0)' }
原因分析
核心原因是SELinux(安全增强型Linux)限制了Web服务器进程(浏览器访问时的运行身份)访问Puppeteer启动Chrome时用到的本地端口:
- 命令行执行时用的是当前用户身份,SELinux对普通用户的限制相对宽松;
- 浏览器访问时,PHP由Web服务器进程(比如
apache或nginx用户)执行,SELinux默认会阻止这类进程发起本地网络连接,导致Puppeteer无法和Chrome的DevTools服务建立WebSocket连接,抛出EACCES错误。
另外还有可能的辅助因素:
- Web服务器用户对Node.js脚本所在目录没有读写权限,无法生成PNG文件;
- Node.js的路径不在Web服务器进程的环境变量中,导致
shell_exec找不到node命令。
解决办法
1. 临时关闭SELinux验证(仅测试用,不推荐长期使用)
执行命令临时关闭SELinux:
setenforce 0
测试如果正常生成PNG,就确认是SELinux的问题。
2. 永久调整SELinux规则(推荐)
允许Web服务器进程发起网络连接:
# Apache或Nginx都适用这条规则 setsebool -P httpd_can_network_connect 1
3. 给Web服务器用户添加目录读写权限
假设脚本和生成文件在/var/www/html/puppeteer目录,执行授权命令:
# Apache用户是apache,Nginx通常是nginx或www-data,根据实际情况替换 chown -R apache:apache /var/www/html/puppeteer chmod -R 755 /var/www/html/puppeteer
4. 在PHP脚本中使用Node.js的绝对路径
避免Web服务器找不到node命令,先通过which node找到绝对路径,再修改PHP脚本:
# 替换成你的node实际路径,比如/usr/bin/node $command = '/usr/bin/node /var/www/html/puppeteer/test.js'; $output = shell_exec($command .' 2>&1'); # 输出错误信息方便调试 echo $output;
内容的提问来源于stack exchange,提问作者elvis chiu
相关产品推荐
相关产品推荐

