Laradock中Puppeteer启动浏览器失败(EACCES)问题求助
Laradock下Artisan调用Puppeteer出现EACCES权限错误的排查与解决
错误重现
执行Laravel Artisan命令craws-data:create调用Node.js爬虫脚本时,Puppeteer启动浏览器抛出权限错误:
Error: Failed to launch the browser process! spawn /root/.cache/puppeteer/chrome/linux-119.0.6045.105/chrome-linux64/chrome EACCES
但直接在终端运行相同Node命令时正常工作。
原因分析
- 运行用户不一致:手动执行Node命令时使用的是
laradock(或当前登录)用户,而Artisan命令默认由Web服务运行用户(如www-data)执行,该用户没有访问/root/.cache目录下Chrome文件的权限——root目录的权限策略严格限制非root用户访问。 - Chrome安装路径归属问题:Puppeteer自动下载的Chrome存放在
root用户的缓存目录中,仅root用户拥有读写执行权限,其他用户无法调用。
解决办法
方法1:调整Chrome文件权限(不推荐,有安全风险)
直接修改Chrome所在目录及文件的权限,让目标执行用户可访问:
# 赋予目录和文件可执行权限 chmod -R 755 /root/.cache/puppeteer/chrome/linux-119.0.6045.105/chrome-linux64/ # 变更目录归属为laradock用户(若Artisan由laradock用户执行) chown -R laradock:laradock /root/.cache/puppeteer/
方法2:在laradock用户下重新安装Puppeteer
切换到laradock用户,重新安装Puppeteer,让Chrome下载到该用户的缓存目录:
su laradock cd /path/to/your/project-directory npm install puppeteer
然后修改index2.js中的executablePath,指向laradock用户缓存下的Chrome:
puppeteer.launch({ headless: true, args: ['--disable-gpu', '--disable-setuid-sandbox', '--no-sandbox', '--no-zygote'], executablePath: '/home/laradock/.cache/puppeteer/chrome/linux-119.0.6045.105/chrome-linux64/chrome' })
方法3:通过sudo切换用户执行Node命令
配置sudo让Web服务用户免密切换到laradock用户执行Node命令:
- 编辑sudoers文件:
visudo
- 添加一行配置(替换Node路径为实际路径):
www-data ALL=(laradock) NOPASSWD: /home/laradock/.nvm/versions/node/v18.19.0/bin/node
- 修改Artisan命令的
handle方法,在shell_exec中加入sudo -u laradock:
public function handle() { $campaign = $this->_getDataToRunJob(); if ($campaign) { $signals = $this->_getSignals(); $keyword = $campaign->keyword; $status = $campaign->status; $nextPage = ".RVQdVd"; $linkCompanyElement = ".yuRUbf a[jsname=UWckNb]"; $timeToStop = $campaign->time_to; $crawsDataId = $campaign->id; $nodePath = '/home/laradock/.nvm/versions/node/v18.19.0/bin/node'; // 加入sudo -u laradock切换用户 shell_exec(sprintf('sudo -u laradock %s crawl-contact-links/index2.js SIGNALS="%s" KEYWORD="%s" STATUS="%s" NEXT_PAGE="%s" LINK_COMPANY_ELEMENT="%s" TIME_TO_STOP="%s" CRAWS_DATA_ID="%s"', $nodePath, $signals, $keyword, $status, $nextPage, $linkCompanyElement, $timeToStop, $crawsDataId)); } }
方法4:移除手动指定的executablePath
删除index2.js中的executablePath配置,让Puppeteer自动检测当前运行用户下的浏览器路径:
puppeteer.launch({ headless: true, args: ['--disable-gpu', '--disable-setuid-sandbox', '--no-sandbox', '--no-zygote'] })
此方法前提是当前执行Node命令的用户(如www-data或laradock)已安装过Puppeteer。
内容的提问来源于stack exchange,提问作者noobmaninasian
相关产品推荐
相关产品推荐

