如何在Chrome中调试无头PDF打印问题?

3

注意:这不是一个关于如何在Chrome中打印PDF的问题,而是一个关于当打印失败时如何获取更多信息的问题。

简言之:我无法解决打印PDF文件的问题,仅出现在某些(可能是大)页面上,需要一些调试帮助来找到实际的问题。

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

我运行的代码是什么?

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

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.

需要注意的是,我在本地机器上运行了这个Docker容器(我的机器有足够的RAM),也在一个Kubernetes集群上运行过,其中该镜像请求了4GBRAM。我还监视了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} &,但似乎也没起作用。

我试图切换到使用直接命令行google-chrome --print-to-pdf=选项,但由于这是一个需要通过登录身份验证的页面,所以我只能将登录页面打印出来,并且似乎存在一些不太好的格式问题。

我曾在我的计算机上运行过这个程序,并成功打印,但是一旦我将同样的代码放入Docker容器中,就会失败。

不幸的是,我不能与您分享此失败页面的链接。


1
不喜欢看到“内存不足。大小=796176”的提示。 - SiHa
这台机器本身有32 GB的RAM,我认为应该足够了。显示的“内存不足”错误来自于Docker容器内部,因此可能存在Docker定义的一些RAM限制? - Chris
1个回答

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

问题似乎源自于Docker挂载的/dev/shm太小,无法执行类似你正在尝试的操作的Chromium。
我发现针对Chromium的已关闭的错误报告提到了这个问题在某些受限环境下(如AWS Lambda和Docker)的存在,它在chromium v65中通过命令行标志--disable-dev-shm-usage得到了解决。
最近的几条评论引用了另一个已关闭的错误报告,关于在chromium v83中命令行标志不能正常工作的问题。它已经在版本84中得到了修复 - 参见评论28

你可以在当前稳定版的Chrome(版本84.0.4147.89及以上)中找到修复。

您提到您正在使用的是Chromium v83,因此您需要更新至至少版本84.0.4147.89,然后使用命令行标志--disable-dev-shm-usage


哇 - 感谢您的帮助 - 我刚刚确认它现在正在工作,并且我正在使用建议的标志v85。 - Chris

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接