Puppeteer运行数小时后启动浏览器失败问题求助
问题描述
使用Puppeteer进行网页数据爬取,初始运行数小时一切正常,但一段时间后会随机停止工作并报错。已查阅相关帖子及StackOverflow问题,但未解决,且报错情况与他人略有不同。
环境说明
通过GitHub workflow将代码部署至Ubuntu VPS,启动Docker容器,工作流使用专门创建的任务用户,怀疑存在权限缺失问题。
报错信息
Error: Failed to launch the browser process! [119330:119330:0503/192600.082150:FATAL:spawn_subprocess.cc(237)] posix_spawn /root/.cache/puppeteer/chrome/linux-135.0.7049.114/chrome-linux64/chrome_crashpad_handler: Operation not permitted (1) TROUBLESHOOTING: https://pptr.dev/troubleshooting at Interface.onClose (/my-app/node_modules/@puppeteer/browsers/lib/cjs/launch.js:325:24) at Interface.emit (node:events:531:35) at Interface.close (node:internal/readline/interface:528:10) at Socket.onend (node:internal/readline/interface:254:10) at Socket.emit (node:events:531:35) at endReadableNT (node:internal/streams/readable:1696:12) at process.processTicksAndRejections (node:internal/process/task_queues:82:21)
核心代码
同一VPS的Docker容器中,另一个仓库使用完全相同的Puppeteer代码却能正常运行无崩溃。
const browser = await puppeteer.launch({ headless: true, args: ["--no-sandbox"], }); try { const page = await browser.newPage(); await page.goto(URL); await page.waitForSelector(".today"); return await page.evaluate(() => { /* ... 数据处理逻辑 ... */ return result; }); } catch (error: any) { logger.error("无法爬取数据:", error); return []; } finally { await browser.close(); }
已尝试的解决方案
- 将Puppeteer从v24.2.0升级至v24.7.2
- 添加可执行路径配置
/usr/bin/chromium - 尝试添加启动参数
--disable-setuid-sandbox、--disable-dev-shm-usage、--disable-features=CrashpadHandler - 尝试添加
--disable-crash-reporter参数
相关配置文件
Dockerfile
# 使用官方Node.js 20镜像 FROM node:20-buster # 安装Puppeteer、Chromium和PostgreSQL客户端所需依赖 RUN apt-get update && apt-get install -y \ fonts-liberation \ libasound2 \ libatk-bridge2.0-0 \ libatk1.0-0 \ libatspi2.0-0 \ libcups2 \ libdbus-1-3 \ libdrm2 \ libgbm1 \ libgtk-3-0 \ libnspr4 \ libnss3 \ libvulkan1 \ libxcomposite1 \ libxdamage1 \ libxfixes3 \ libxkbcommon0 \ libxrandr2 \ xdg-utils \ wget \ curl \ chromium # 启用corepack管理Yarn RUN corepack enable # 创建并设置工作目录 WORKDIR /bot-feed # 先复制package文件(优化缓存) COPY package.json yarn.lock ./ # 安装依赖 RUN yarn install # 复制TS源码及其他文件 COPY . . # 启动机器人 CMD ["yarn", "run", "start"]
docker-compose.yml
services: bot-feed: build: . image: twitter-bot:1.0.0 container_name: twitter-bot env_file: - .env networks: - cr-station networks: cr-station: driver: bridge
github-workflow.yml
name: Deployment Workflow on: push: branches: ["main"] jobs: deploy: runs-on: ubuntu-latest steps: - name: 🛠️ 检出代码 uses: actions/checkout@v3 - name: 🚀 部署代码 uses: appleboy/scp-action@v0.1.7 with: host: ${{ secrets.SSH_HOST }} username: ${{ secrets.SSH_USER }} key: ${{ secrets.SSH_KEY }} source: "./" target: "~/bot-feed" - name: 🚀 在VPS上执行部署命令 uses: appleboy/ssh-action@v0.1.7 with: host: ${{ secrets.SSH_HOST }} username: ${{ secrets.SSH_USER }} key: ${{ secrets.SSH_KEY }} script: | cd ~/bot-feed yarn install yarn run docker
问题分析与解决方案
核心原因
报错指向chrome_crashpad_handler启动失败,提示"Operation not permitted",结合环境来看,主要有两个可能:
- 容器内用户权限问题:当前Docker容器以root用户运行,Puppeteer默认在
/root/.cache下下载Chrome,后续运行时可能因权限变更或系统安全模块限制,导致无法启动crashpad进程。 - 缓存目录冲突:虽然安装了系统级Chromium,但Puppeteer仍优先使用自行下载的Chrome版本,多次运行后缓存目录权限可能出现异常。
针对性解决方案
1. 在Docker容器内创建非root用户运行
容器以root运行存在安全风险,也容易触发权限限制,修改Dockerfile添加非root用户:
# ... 原有内容 ... # 创建非root用户并赋予工作目录权限 RUN useradd -m appuser && chown -R appuser:appuser /bot-feed USER appuser # 启动机器人 CMD ["yarn", "run", "start"]
2. 强制Puppeteer使用系统安装的Chromium
避免Puppeteer自行下载Chrome,指定系统Chromium路径并禁用crashpad相关功能:
修改Puppeteer启动配置:
const browser = await puppeteer.launch({ headless: true, args: [ "--no-sandbox", "--disable-setuid-sandbox", "--disable-dev-shm-usage", "--disable-features=CrashpadHandler", "--disable-crash-reporter" ], executablePath: "/usr/bin/chromium", defaultViewport: null, });
同时在Dockerfile中添加环境变量,禁止Puppeteer下载浏览器:
# ... 原有内容 ... # 添加环境变量,禁用Puppeteer自动下载浏览器 ENV PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=true ENV PUPPETEER_EXECUTABLE_PATH=/usr/bin/chromium # ... 原有内容 ...
3. 检查VPS的安全限制
确认VPS是否启用了SELinux或AppArmor,这些安全模块可能阻止容器内进程启动crashpad。可临时关闭测试:
# 临时关闭SELinux sudo setenforce 0 # 临时关闭AppArmor sudo systemctl stop apparmor
如果关闭后恢复正常,需配置相应规则允许容器内进程操作。
验证建议
修改配置后重新部署,观察是否仍出现随机崩溃。由于另一个仓库能正常运行,可对比两个仓库的Docker镜像构建日志,确认是否存在依赖或权限差异。
内容的提问来源于stack exchange,提问作者Neeko
相关产品推荐
相关产品推荐

