V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
missz
V2EX  ›  Node.js

puppeteer 运行一段时间后无法启动

  •  1
     
  •   missz · 2021-01-18 10:11:54 +08:00 · 3921 次点击
    这是一个创建于 1406 天前的主题,其中的信息可能已经有所发展或是发生改变。

    puppeteer 运行大概一周后,就无法再打开 chrome 进程了,在这期间会非常频繁的打开关闭 browser

    重现步骤

    • Puppeteer version: [email protected]
    • Platform / OS version: centos7.4
    • Node.js version:v12

    以下为伪代码,部分业务处理已移除

        try {
            let proxy = await jsonUtil.getProxy();
            logger.info("proxy", proxy);
            let proxy_server = 'http://' + proxy.ip + ':' + proxy.port
            const launch_options = {
                headless: true,
                ignoreDefaultArgs: ['--enable-automation', '--window-size=1440,1024',
                    '--proxy-server=' + proxy_server,
                    '--user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.103 Safari/537.36',
                    '--disable-extensions'],
                dumpio: true, autoClose: true, devtools: false,
                args: ['--no-sandbox', '--disable-gpu', '--disable-dev-shm-usage']
            };
            browser = await puppeteer.launch(launch_options);
            const pages = await browser.pages();
            if (common.proxyName !== null) {
                await page.authenticate({username: common.proxyName, password: common.proxyPwd});
            }
            await page.setViewport({width: 1440, height: 1024});
            await page.setDefaultNavigationTimeout(45000);
            await page.goto('http://localhost:8085/crackByGt?gt=' + data.gt + "&challenge=" + data.challenge, {waitUntil: 'networkidle0'});
           //Some business processing
        } catch (e) {
            logger.error("error", e)
        } finally {
            await page.close();
            await browser.close();
            logger.info("浏览器关闭完成")
        }
    

    除此之外,还有一个 kill 长时间未关闭的 shell 脚本,目的是杀死超过 12 小时未关闭的 chrome-linux 进程

    #!/bin/bash
    #please specify the process run time,which you want to kill
    run_tim=12
    pid=`ps -ef | grep chrome-linux | awk '{print $2}'`
    for i in $pid
    do
    	number=`ps -p $i -o etime | wc -l`
    		if [ $number -eq 2 ];then
    			tim=`ps -p $i -o etime | awk -F ":" 'NR==2{print $1}'`
    				if [ $tim -ge ${run_tim} ];then
    					kill -9 $i
    				fi
    		else
    			continue
    		fi
    done
    
    

    以下为错误信息:

    [2021-01-17T08:00:19.648] [ERROR] jiyan - 异常 Error: Failed to launch the browser process! spawn /opt/bbd_verify_nodejs/node_modules/[email protected]@puppeteer/.local-chromium/linux-818858/chrome-linux/chrome EAGAIN
    TROUBLESHOOTING: https://github.com/puppeteer/puppeteer/blob/main/docs/troubleshooting.md
    
        at onClose (/opt/bbd_verify_nodejs/node_modules/[email protected]@puppeteer/lib/cjs/puppeteer/node/BrowserRunner.js:193:20)
        at ChildProcess.<anonymous> (/opt/bbd_verify_nodejs/node_modules/[email protected]@puppeteer/lib/cjs/puppeteer/node/BrowserRunner.js:185:85)
        at ChildProcess.emit (events.js:311:20)
        at Process.ChildProcess._handle.onexit (internal/child_process.js:273:12)
        at onErrorNT (internal/child_process.js:469:16)
        at processTicksAndRejections (internal/process/task_queues.js:84:21)
    
    [2021-01-17T08:00:19.770] [ERROR] jiyan - 异常 Error: Failed to launch the browser process!
    [0117/080019.402868:FATAL:zygote_host_impl_linux.cc(174)] Check failed: process.IsValid(). Failed to launch zygote process
    #0 0x5619c2f86b39 base::debug::CollectStackTrace()
    #1 0x5619c2ef94c3 base::debug::StackTrace::StackTrace()
    #2 0x5619c2f09c80 logging::LogMessage::~LogMessage()
    #3 0x5619c2f0a84e logging::LogMessage::~LogMessage()
    #4 0x5619c199c59c content::ZygoteHostImpl::LaunchZygote()
    #5 0x5619c2ea476a content::(anonymous namespace)::LaunchZygoteHelper()
    #6 0x5619c0f678d6 content::ZygoteCommunication::Init()
    #7 0x5619c0f67fd7 content::CreateUnsandboxedZygote()
    #8 0x5619c2ea3d46 content::ContentMainRunnerImpl::Initialize()
    #9 0x5619c2ea1e0b content::RunContentProcess()
    #10 0x5619c2ea1f5c content::ContentMain()
    #11 0x5619c2ef33d2 headless::(anonymous namespace)::RunContentMain()
    #12 0x5619c2ef30bc headless::HeadlessShellMain()
    #13 0x5619c04f4a03 ChromeMain
    #14 0x7f3f7349f555 __libc_start_main
    #15 0x5619c04f482a _start
    
    Received signal 6
    #0 0x5619c2f86b39 base::debug::CollectStackTrace()
    #1 0x5619c2ef94c3 base::debug::StackTrace::StackTrace()
    #2 0x5619c2f866db base::debug::(anonymous namespace)::StackDumpSignalHandler()
    #3 0x7f3f78e35630 (/usr/lib64/libpthread-2.17.so+0xf62f)
    #4 0x7f3f734b3387 __GI_raise
    #5 0x7f3f734b4a78 __GI_abort
    #6 0x5619c2f85665 base::debug::BreakDebugger()
    #7 0x5619c2f0a0f2 logging::LogMessage::~LogMessage()
    #8 0x5619c2f0a84e logging::LogMessage::~LogMessage()
    #9 0x5619c199c59c content::ZygoteHostImpl::LaunchZygote()
    #10 0x5619c2ea476a content::(anonymous namespace)::LaunchZygoteHelper()
    #11 0x5619c0f678d6 content::ZygoteCommunication::Init()
    #12 0x5619c0f67fd7 content::CreateUnsandboxedZygote()
    #13 0x5619c2ea3d46 content::ContentMainRunnerImpl::Initialize()
    #14 0x5619c2ea1e0b content::RunContentProcess()
    #15 0x5619c2ea1f5c content::ContentMain()
    #16 0x5619c2ef33d2 headless::(anonymous namespace)::RunContentMain()
    #17 0x5619c2ef30bc headless::HeadlessShellMain()
    #18 0x5619c04f4a03 ChromeMain
    #19 0x7f3f7349f555 __libc_start_main
    #20 0x5619c04f482a _start
      r8: 0000000000000000  r9: 0000000000000000 r10: 0000000000000008 r11: 0000000000000202
     r12: 00001db7754aedc0 r13: aaaaaaaaaaaaaaaa r14: 00001db7754aedd0 r15: 00007fffdb5a2270
      di: 000000000000217f  si: 000000000000217f  bp: 00007fffdb5a1a20  bx: 00007fffdb5a2290
      dx: 0000000000000006  ax: 0000000000000000  cx: ffffffffffffffff  sp: 00007fffdb5a18e8
      ip: 00007f3f734b3387 efl: 0000000000000202 cgf: 0000000000000033 erf: 0000000000000000
     trp: 0000000000000000 msk: 0000000000000000 cr2: 0000000000000000
    [end of stack trace]
    Calling _exit(1). Core file will not be generated.
    
    14 条回复    2021-01-18 16:42:08 +08:00
    guochao
        1
    guochao  
       2021-01-18 10:39:39 +08:00
    我原来遇到过 chrome 标签无法自己关闭的情况,所以后来是用了 cgroup 啊、timeout 啊之类的工具,来清理 chrome 进程。

    你上面贴的信息不足以得到为什么启动不了进程的原因。原因有很多,比如说资源不够了( pid,mem,……)。我没读过 chromium 实现,但是有没有可能是用了同一个 profile ?用同样的参数能不能手动启动一个 headless chromium ?

    建议先自己再调研一下
    WishMeLz
        2
    WishMeLz  
       2021-01-18 10:52:33 +08:00
    这个东西我在服务器里面运行不成功,我也不知道什么原因。我只能在我的电脑里面运行
    Areym
        3
    Areym  
       2021-01-18 11:08:35 +08:00
    建议每次只开一个浏览器进程 然后每次新开一个标签页做任务 完事之后关闭标签页 不关闭浏览器
    guochao
        4
    guochao  
       2021-01-18 11:40:55 +08:00
    @WishMeLz 可能性有几个,一个是这玩意儿依赖 X,是不是什么库没有装。另一个是 chromium 带了几种沙箱实现,是不是这几种沙箱都不能正常工作,不能正常工作的话会失败。

    @missz 想起来忘了说的一个问题。你加了'--no-sandbox',建议还是不要这个。在代码里面修一下 sandbox 的权限,sandbox 文件的 owner 需要是 root ( puppeteer 解压以后是当前用户,需要 chown ),并且需要 chmod u+s 来让当前用户下执行的程序自动切换到 root (用来配置沙箱环境限制子进程)。而且,对,推荐用 @Areym #2 提到的开标签页做事儿。
    lozzow
        5
    lozzow  
       2021-01-18 11:57:35 +08:00 via iPhone
    可以尝试使用 docker 版本的,然后直接退出 docker 来清理资源
    Justin13
        6
    Justin13  
       2021-01-18 12:52:05 +08:00 via Android
    加参数"--no-zygote"
    missz
        7
    missz  
    OP
       2021-01-18 13:34:59 +08:00
    @Areym 因为需要频繁切换代理 ip,不能给每个标签设置代理
    missz
        8
    missz  
    OP
       2021-01-18 13:40:20 +08:00
    @Justin13 这个好像是不允许 zygote 进程创建 fork 子进程,但是没有在服务器上找到 zygote 相关的进程
    libook
        9
    libook  
       2021-01-18 13:42:19 +08:00
    我在自己的 Server 上跑 puppeteer 就很难跑起来,这个可能和依赖有关系,比如虽然是 headless 模式,但可能依然依赖一些 GUI 的东西。

    再加上缓存管理之类的事情,我后来就换容器搞了,出问题直接回退镜像。

    可以直接去找一些可用的 puppeteer 镜像,自己改。
    missz
        10
    missz  
    OP
       2021-01-18 14:05:22 +08:00
    @libook 目前公司所有服务器环境都没有使用 docker,并且这个程序已经上线到正式了,服务器环境相对固定了,换成 docker 上面不会同意
    Justin13
        11
    Justin13  
       2021-01-18 14:40:07 +08:00 via Android
    @missz
    "FATAL:zygote_host_impl_linux.cc(174)] Check failed: process.IsValid(). Failed to launch zygote process"
    Itoktsnhc
        12
    Itoktsnhc  
       2021-01-18 14:44:38 +08:00
    有一个 browerless 的项目 https://github.com/browserless/chrome 他应该就是集成了很多清理 /重启这些额外的管理功能。我们目前有服务有部分用到他的 docker 镜像,但是没试过自己源码部署
    lozzow
        13
    lozzow  
       2021-01-18 15:34:39 +08:00
    @missz 我看了下你的日志关键字,和我们公司使用的是同一个业务场景😂现在公司也是用的物理机部署,用命名空间做隔离,但是后面还是做了 docker 容器化的处理,只是由于线上业务很稳定,没有正式上线,但是容器化之后对于业务扩展和资源控制,有很好的提升
    missz
        14
    missz  
    OP
       2021-01-18 16:42:08 +08:00
    通过核查服务器情况:
    1 ):内存、cpu 相对正常
    2 ):用户子进程达到系统上限(也是出现异常的原因)
    3 ):chromium 所依赖的库确认都有安装

    目前的问题:
    1 ):kill 进程的脚本似乎会导致 puppeteer 无法再打开浏览器(存疑)
    2 ):@Justin13 老哥提出的--no-zygote 需要到测试环境验证一段时间,暂时不能确定是否是该参数的问题
    3 ):@Itoktsnhc @lozzow 两位老哥提出的容器化可以解决问题,但是人为环境阻力太大,只能仅限于本地,淦
    4 ):@guochao 老哥提出的沙箱环境多次测试目前还是没能启动起来。。。

    目前的解决方案

    进程满了用脚本重启。。。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2708 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 10:27 · PVG 18:27 · LAX 02:27 · JFK 05:27
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.