WSL运行Chrome Headless模式

前言

Google Chrome早就支持了headless模式,但一般都是在Linux上运行,而我则习惯于在WSL上开发,折腾了好久终于找到了可以在WSL上跑headless模式的方法。

以下以WSL中安装的是Ubuntu 18.04系统为例。

常见安装方法

安装依赖库

$ sudo apt install gconf-service libasound2 libatk1.0-0 libc6 libcairo2 libcups2 libdbus-1-3 libexpat1 libfontconfig1 libgcc1 libgconf-2-4 libgdk-pixbuf2.0-0 libglib2.0-0 libgtk-3-0 libnspr4 libpango-1.0-0 libpangocairo-1.0-0 libstdc++6 libx11-6 libx11-xcb1 libxcb1 libxcomposite1 libxcursor1 libxdamage1 libxext6 libxfixes3 libxi6 libxrandr2 libxrender1 libxss1 libxtst6 ca-certificates fonts-liberation libappindicator3-1 libnss3 lsb-release xdg-utils

安装Chrome

$ wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb
$ sudo dpkg -i google-chrome-stable_current_amd64.deb
$ which google-chrome
/usr/bin/google-chrome

使用Chrome Headless访问网页

使用 官方文档的方法打开Chrome:

$ google-chrome --headless --disable-gpu --screenshot https://www.baidu.com/

出现如下报错信息:

Failed to move to new namespace: PID namespaces supported, Network namespace supported, but failed: errno = Permission denied
Failed to generate minidump.Illegal instruction (core dumped)

使用如下命令行也不行:

$ google-chrome --no-sandbox --headless --no-gpu --disable-setuid-sandbox --screenshot http://www.baidu.com/

[0829/140949.035033:WARNING:gpu_process_host.cc(1188)] The GPU process has crashed 1 time(s)
[0829/140950.200613:WARNING:gpu_process_host.cc(1188)] The GPU process has crashed 2 time(s)
[0829/140951.306996:WARNING:gpu_process_host.cc(1188)] The GPU process has crashed 3 time(s)

增加--single-process参数后打印如下信息:

[0829/141145.431580:ERROR:browser_main_loop.cc(584)] Failed to put Xlib into threaded mode.
[0829/141146.090239:INFO:headless_shell.cc(572)] Written to file screenshot.png.

虽然看起来有报错,但是的确生成网页截图了。

screenshot.png显示如下:

看起来有两个问题:

  • 中文没有正确显示
  • 窗口大小偏小

中文显示的问题可以通过以下命令解决:

$ sudo apt install fonts-noto-cjk

修改窗口大小可以通过增加--window-size=1920,1080参数进行修改。

开启远程调试

Headless模式下一般需要通过Chrome远程调试协议进行访问。

命令行增加--remote-debugging-port=9200参数启动Chrome后,打印出以下信息:

[0829/194236.072838:ERROR:browser_main_loop.cc(584)] Failed to put Xlib into threaded mode.

DevTools listening on ws://127.0.0.1:9200/devtools/browser/18442c9f-b0ee-4149-a16b-f49622047621
[0829/194236.299565:ERROR:command_buffer_proxy_impl.cc(107)] ContextResult::kTransientFailure: Shared memory region is not valid

看起来调试端口是启动成功了。

但是在访问调试页面后,Chrome进程Crash了。

Segmentation fault (core dumped)

试了多个页面后发现,远程调试都会导致Crash,看来这条路不太好走。

使用puppeteer提供的Chrome

无意中发现,puppeteer中提供的Chrome竟然可以在WSL中开启调试端口并正常访问。

puppeteer默认下载地址的格式为:https://storage.googleapis.com/chromium-browser-snapshots/${platform}/${revision}/chrome-${revision}.zip。例如目前Linux上最新版本的URL为:https://storage.googleapis.com/chromium-browser-snapshots/Linux_x64/674921/chrome-linux.zip

也可以使用镜像网站下载,例如:https://npm.taobao.org/mirrors/chromium-browser-snapshots/

解压出来就可以直接用了。

总结

  • 安装依赖库,包括中文字体库
  • 使用puppeteer提供的Chrome版本
  • 完整的启动命令行:chrome --no-sandbox --headless --no-gpu --disable-setuid-sandbox --single-process --window-size=1920,1080 --screenshot --remote-debugging-port=9200 http://www.baidu.com/

顺便提供一下puppeteer使用的完整命令行:

chrome --disable-background-networking --enable-features=NetworkService,NetworkServiceInProcess --disable-background-timer-throttling --disable-backgrounding-occluded-windows --disable-breakpad --disable-client-side-phishing-detection --disable-component-extensions-with-background-pages --disable-default-apps --disable-dev-shm-usage --disable-extensions --disable-features=site-per-process,TranslateUI,BlinkGenPropertyTrees --disable-hang-monitor --disable-ipc-flooding-protection --disable-popup-blocking --disable-prompt-on-repost --disable-renderer-backgrounding --disable-sync --force-color-profile=srgb --metrics-recording-only --no-first-run --enable-automation --password-store=basic --use-mock-keychain --headless --hide-scrollbars --mute-audio about:blank --no-sandbox --disable-setuid-sandbox --remote-debugging-port=0 --user-data-dir=/tmp/puppeteer_dev_profile-NkEdQ6
分享