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

Chr*_*ris 3 chromium selenium-chromedriver docker google-chrome-headless

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

\n

简而言之:我无法解决打印 PDF 问题,该问题仅发生在某些(可能很大)页面上,并且可以在调试实际问题时使用一些帮助。

\n

背景:我正在使用 chromedriver (v83) 和 chromium-browser (v83) 通过 python selenium 从网页打印 PDF 文件。我正在构建一个 docker 映像来包含所需的依赖项。我尝试过使用 Debian(buster 和stretch)以及 Alpine 基本映像,但在尝试打印某些页面时最终都会导致相同的错误。奇怪的是,对于其他(较小的)页面,打印可以工作,但是当要打印许多资源和页面时,打印失败。我可能会补充一点,这个 docker 镜像最终会在 Kubernetes 集群内部运行,我在其中分配了高达 4GB 的 RAM。

\n

我正在运行什么代码?

\n

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

\n
from selenium import webdriver\n\nappState = {\n    "recentDestinations": [\n        {\n            "id": "Save as PDF",\n            "origin": "local"\n        }\n    ],\n    "selectedDestinationId": "Save as PDF",\n    "version": 2\n}\n\ndef get_chrome_options(headless: bool, enable_logging: bool) -> Options:\n    chrome_options = webdriver.ChromeOptions()\n    profile = {'printing.print_preview_sticky_settings.appState': json.dumps(appState)}\n\n    chrome_options.add_experimental_option('prefs', profile)\n    if headless:\n        chrome_options.add_argument('--headless')\n        chrome_options.add_argument('--no-sandbox')\n    chrome_options.add_argument('--window-size=1920,1080')\n    chrome_options.add_argument('--disable-gpu')\n    chrome_options.add_argument('--disable-web-security')\n    chrome_options.add_argument('-\xe2\x80\x93allow-file-access-from-files')\n    chrome_options.add_argument('--run-all-compositor-stages-before-draw')\n    chrome_options.add_argument('--kiosk-printing')\n\n    if enable_logging:\n        chrome_options.add_argument('--enable-logging')\n\n    return chrome_options\n\ndef print_the_page(url):\n    driver = webdriver.Chrome(chrome_options=get_chrome_options(headless, enable_logging))\n    driver.execute(driver_command=Command.GET, params={'url': url})\n    command_url = f"{driver.command_executor._url}/session/{driver.session_id}/chromium/send_command_and_get_result"\n    response = driver.command_executor._request('POST', command_url, json.dumps({'cmd': 'Page.printToPDF', 'params': {}}))\n\n
Run Code Online (Sandbox Code Playgroud)\n

然后会发生什么?

\n

对于某些页面,这会失败 - 意思是 - 中存在以下消息response

\n
{'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":""}}'}\n
Run Code Online (Sandbox Code Playgroud)\n

[更新]

\n

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

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

在这里我要指出的是,我一直在我的机器(具有足够的 RAM)以及 Kubernetes 集群上本地运行这个 docker 容器,其中该映像请求 4GB RAM。我还监控了 RAM 使用情况,这似乎不是一个问题 - 不过 - 如果 RAM 使用量非常高,以至于 chrome 无法正常工作,并且您从未在总体 RAM 使用情况中真正看到这一点,那么这可能是幻觉。

\n

[更新2]

\n

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

\n
\xe2\x94\x82 [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\n...\n\xe2\x94\x82 [0923/141758.393923:WARNING:dns_config_service_posix.cc(341)] Failed to read DnsConfig.                                                                                                       \xe2\x94\x82\n\xe2\x94\x82 [0923/141758.401925:ERROR:zygote_host_impl_linux.cc(262)] Failed to adjust OOM score of renderer with pid 32: Permission denied (13)                                                          \xe2\x94\x82\n\xe2\x94\x82 [0923/141758.413475:ERROR:zygote_host_impl_linux.cc(262)] Failed to adjust OOM score of renderer with pid 36: Permission denied (13) \n... loading all the resources ...\n\xe2\x94\x82 [0923/141824.611661:ERROR:print_render_frame_helper.cc(1889)] Printing failed.                                                                                                                \xe2\x94\x82\n\xe2\x94\x82 [0923/141824.612439:ERROR:headless_shell.cc(562)] Print to PDF failed  \n
Run Code Online (Sandbox Code Playgroud)\n

有什么问题?

\n

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

\n

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

\n

我还尝试过什么?

\n

我最初是在 Debian buster 下使用最新版本google-chromechromium二进制文件(v85)运行它。我已切换到 Alpine 基础映像,并chromium希望这可能会改变一些东西,但事实并非如此。

\n

我尝试过在Docker中设置Xvfb ${DISPLAY} -screen ${SCREEN} ${RESOLUTION} &,但似乎也没有任何效果。

\n

我尝试切换到使用直接 cligoogle-chrome --print-to-pdf=选项,但由于它是一个需要通过登录身份验证的页面,因此我只能打印登录页面,而且它似乎还存在一些不太好的格式问题。

\n

我一直在我的机器上、Docker 之外运行它,并且能够按预期打印,但是一旦我将相同的代码放入 Docker 容器中,它就会失败。

\n

不幸的是,我无法与您分享失败的页面。

\n

Kla*_*con 7

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

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

这个问题似乎源于 Docker 的安装/dev/shm太小,Chromium 无法完成您想要做的事情。

我发现了一份针对 chromium 的已关闭错误报告,在某些有限的环境(例如 AWS Lambda 和 Docker)中引用了此问题,该问题已在 chromium v​​65 中的命令行标志后面修复--disable-dev-shm-usage

最后几条评论引用了有关 chromium v​​83 中此问题的另一个错误报告(现已关闭),其中命令行标志无法正常工作。它已在版本 84 中修复 - 根据评论 28

您可以在 Chrome 的当前稳定版本(版本 84.0.4147.89 及更高版本)中找到修复程序。

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