注意:这不是一个关于如何在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-chrome
和chromium
二进制文件(v85)运行此程序。我已经切换到Alpine基础镜像和chromium
- 希望这可能会改变一些东西,但它并没有。
我尝试在Docker中设置Xvfb ${DISPLAY} -screen ${SCREEN} ${RESOLUTION} &
,但似乎也没起作用。
我试图切换到使用直接命令行google-chrome --print-to-pdf=
选项,但由于这是一个需要通过登录身份验证的页面,所以我只能将登录页面打印出来,并且似乎存在一些不太好的格式问题。
我曾在我的计算机上运行过这个程序,并成功打印,但是一旦我将同样的代码放入Docker容器中,就会失败。
不幸的是,我不能与您分享此失败页面的链接。