如何调试 chrome 中的无头 pdf 打印问题?

How to debug headless pdf printing problems in chrome?

注意:这是不是(直接)关于如何在chrome中打印PDF的问题,而是关于打印失败时如何获取更多信息的问题

简而言之:我无法解决打印 PDF 的问题,该问题只发生在某些(可能是大的)页面上,需要一些帮助来调试实际问题。

背景: 我正在使用 chrome 驱动程序 (v83) 和铬浏览器 (v83) 通过利用 python 从网页打印 PDF 文件硒。我正在构建一个 docker 图像以包含为此所需的依赖项。我曾尝试使用 Debian(buster 和 stretch)以及 Alpine 基础映像,但在尝试打印 some 页面时,所有这些最终都会导致相同的错误。奇怪的是,对于其他(较小的)页面,打印工作正常,但是当要打印许多资产和页面时,打印失败。我可能会补充说,这个 docker 图像最终会 运行 在 Kubernetes 集群中,我在其中分配了多达 4GB 的 RAM。

我是什么密码运行ning?

这个项目是为python3编写的,所以这里有一些相关的代码片段。请注意,我在此处删除了所有错误处理和等待页面加载完成。

from selenium import webdriver

appState = {
    "recentDestinations": [
        {
            "id": "Save as PDF",
            "origin": "local"
        }
    ],
    "selectedDestinationId": "Save as PDF",
    "version": 2
}

def get_chrome_options(headless: bool, enable_logging: bool) -> Options:
    chrome_options = webdriver.ChromeOptions()
    profile = {'printing.print_preview_sticky_settings.appState': json.dumps(appState)}

    chrome_options.add_experimental_option('prefs', profile)
    if headless:
        chrome_options.add_argument('--headless')
        chrome_options.add_argument('--no-sandbox')
    chrome_options.add_argument('--window-size=1920,1080')
    chrome_options.add_argument('--disable-gpu')
    chrome_options.add_argument('--disable-web-security')
    chrome_options.add_argument('-–allow-file-access-from-files')
    chrome_options.add_argument('--run-all-compositor-stages-before-draw')
    chrome_options.add_argument('--kiosk-printing')

    if enable_logging:
        chrome_options.add_argument('--enable-logging')

    return chrome_options

def print_the_page(url):
    driver = webdriver.Chrome(chrome_options=get_chrome_options(headless, enable_logging))
    driver.execute(driver_command=Command.GET, params={'url': url})
    command_url = f"{driver.command_executor._url}/session/{driver.session_id}/chromium/send_command_and_get_result"
    response = driver.command_executor._request('POST', command_url, json.dumps({'cmd': 'Page.printToPDF', 'params': {}}))

然后会发生什么?

对于 一些 页面,此操作失败 - 意思 - response:

中有此消息
{'status': 500, 'value': '{"value":{"error":"unknown error","message":"unknown error: unhandled inspector error: {\"code\":-32000,\"message\":\"Printing failed\"}\n  (Session info: headless chrome=83.0.4103.116)","stacktrace":""}}'}

[更新]

我在直接使用 --print-to-pdf 选项时设法产生了更多错误输出,这似乎暗示这里存在“内存不足”问题:

[0923/135406.102857:WARNING:discardable_shared_memory_manager.cc(194)] Less than 64MB of free space in temporary directory for shared memory files: 23
[0923/135406.110108:WARNING:dns_config_service_posix.cc(341)] Failed to read DnsConfig.
[0923/135406.180892:WARNING:dns_config_service_posix.cc(341)] Failed to read DnsConfig.
[0923/135406.613221:FATAL:memory.cc(38)] Out of memory. size=796176
Received signal 6
  r8: 00007fa6f39dadc4  r9: 0000000000000000 r10: 0000000000000008 r11: 0000000000000246
 r12: 0000557efd1b0660 r13: 0000000000000000 r14: 00007fa6f39db240 r15: 0000000000000043
  di: 0000000000000002  si: 00007fa6f39dac90  bp: 00007fa6f39dac90  bx: 0000000000000000
  dx: 0000000000000000  ax: 0000000000000000  cx: 00007fa6fd347a71  sp: 00007fa6f39dac88
  ip: 00007fa6fd347a71 efl: 0000000000000246 cgf: 002b000000000033 erf: 0000000000000000
 trp: 0000000000000000 msk: 0000000000000000 cr2: 0000000000000000
[end of stack trace]
Calling _exit(1). Core file will not be generated.
[0923/135406.626313:ERROR:headless_shell.cc(399)] Abnormal renderer termination.

我会在这里指出,我已经 运行 在我的机器(有足够的 RAM)以及请求此图像的 Kubernetes 集群上本地 docker 容器4GB 内存。我还监视了 RAM 使用情况,这似乎不是问题 - 虽然 - 如果 RAM 使用率非常高以至于 chrome 只是失败并且您从未真正在整体 RAM 使用情况中看到它,那可能是虚幻的.

[更新 2]

我尝试再次使用 --print-to-pdf 选项,但我也发现了问题。正在加载资源,但是打印还是失败

│ [0923/144355.169080:ERROR:bus.cc(393)] Failed to connect to the bus: Failed to connect to socket /var/run/dbus/system_bus_socket: No such file or directory
...
│ [0923/141758.393923:WARNING:dns_config_service_posix.cc(341)] Failed to read DnsConfig.                                                                                                       │
│ [0923/141758.401925:ERROR:zygote_host_impl_linux.cc(262)] Failed to adjust OOM score of renderer with pid 32: Permission denied (13)                                                          │
│ [0923/141758.413475:ERROR:zygote_host_impl_linux.cc(262)] Failed to adjust OOM score of renderer with pid 36: Permission denied (13) 
... loading all the resources ...
│ [0923/141824.611661:ERROR:print_render_frame_helper.cc(1889)] Printing failed.                                                                                                                │
│ [0923/141824.612439:ERROR:headless_shell.cc(562)] Print to PDF failed  

问题是什么?

我怎样才能获得有关“打印失败”原因的更多信息 - 不幸的是,“未知错误:未处理的检查器错误”没有给我任何关于如何继续的想法。

是否可能有任何其他标志可以从 chrome 获得更多调试输出,或者是否有我应该能够找到的日志?

我还尝试了什么?

我最初是在 Debian buster 下使用最新的 google-chromechromium 二进制文件 (v85) 运行 进行此操作。我已经切换到 Alpine 基础映像和 chromium - 希望这可能会改变一些东西,但它没有。

我试过在Docker中设置Xvfb ${DISPLAY} -screen ${SCREEN} ${RESOLUTION} &,但好像也没什么效果。

我试过改用direct cli google-chrome --print-to-pdf=选项,但是由于是需要登录认证的页面,所以只能打印登录页面,而且好像也有一些不太好的格式问题。

我已经 运行 在 Docker 之外的机器上安装了它,并且能够按预期打印,但是一旦我将相同的代码放入 Docker 容器,它失败了。

很遗憾,我无法与您分享失败的页面。

您日志中的相关警告似乎是这样的:

[0923/135406.102857:WARNING:discardable_shared_memory_manager.cc(194)] Less than 64MB of free space in temporary directory for shared memory files: 23

问题似乎源于 Docker 安装的 /dev/shm 对于 Chromium 来说太小而无法像您尝试做的那样。

我发现 closed bug report 在某些有限环境(例如 AWS Lambda 和 Docker 中针对 chromium 引用了此问题,它已在命令行标志 --disable-dev-shm-usage 后面的 chromium v​​65 中修复。

最后几条评论参考another bug report (now closed) about this issue in chromium v83 where the command line flag was not working properly. It has been fixed in version 84 - per comment 28:

You can find the fix in current stable release of Chrome (version 84.0.4147.89 and above).

您已表明您使用的是 chromium v​​83,因此您需要至少更新版本 84.0.4147.89,然后使用命令行标志 --disable-dev-shm-usage