Linux下直接执行正常,Java调用含Selenium的Python脚本失败如何解决?
解决Java调用Python脚本时ChromeDriver意外退出(状态码-11)的问题
问题背景
我有一个用pyhtml2pdf实现的HTML转PDF的Python脚本:
import os import sys from pyhtml2pdf import converter def convert_html_to_pdf(html_path, pdf_path): absolute_html_path = os.path.abspath(html_path) converter.convert(f'file:///{absolute_html_path}', pdf_path, 60, False, 0, False) if __name__ == "__main__": if len(sys.argv) != 3: print("Usage: python3 test.py <html_path> <pdf_path>") else: html_path = sys.argv[1] pdf_path = sys.argv[2] convert_html_to_pdf(html_path, pdf_path)
在Linux服务器上直接执行以下命令完全正常,能生成PDF:
DISPLAY=:99 python3 test.py 298.html 298.pdf
但通过Java程序调用时:
String comds = "DISPLAY=:99 python3 test.py 298.html 298.pdf"; Runtime.getRuntime().exec(comds);
出现错误:
2024-09-27 11:33:14 - ERROR>Traceback (most recent call last): 2024-09-27 11:33:14 - ERROR> File "test.py", line 15, in <module> 2024-09-27 11:33:14 - ERROR> convert_html_to_pdf(html_path, pdf_path) 2024-09-27 11:33:14 - ERROR> File "test.py", line 7, in convert_html_to_pdf 2024-09-27 11:33:14 - ERROR> converter.convert(f'file:///{absolute_html_path}', pdf_path, 20, False, 0, False) 2024-09-27 11:33:14 - ERROR> File "/usr/local/lib/python3.6/site-packages/pyhtml2pdf/converter.py", line 39, in convert 2024-09-27 11:33:14 - ERROR> source, timeout, install_driver, print_options) 2024-09-27 11:33:14 - ERROR> File "/usr/local/lib/python3.6/site-packages/pyhtml2pdf/converter.py", line 79, in __get_pdf_from_html 2024-09-27 11:33:14 - ERROR> driver = webdriver.Chrome(options=webdriver_options) 2024-09-27 11:33:14 - ERROR> File "/usr/local/lib/python3.6/site-packages/selenium/webdriver/chrome/webdriver.py", line 73, in __init__ 2024-09-27 11:33:14 - ERROR> self.service.start() 2024-09-27 11:33:14 - ERROR> File "/usr/local/lib/python3.6/site-packages/selenium/webdriver/common/service.py", line 98, in start 2024-09-27 11:33:14 - ERROR> self.assert_process_still_running() 2024-09-27 11:33:14 - ERROR> File "/usr/local/lib/python3.6/site-packages/selenium/webdriver/common/service.py", line 111, in assert_process_still_running 2024-09-27 11:33:14 - ERROR> % (self.path, return_code) 2024-09-27 11:33:14 - ERROR>selenium.common.exceptions.WebDriverException: Message: Service chromedriver unexpectedly exited. Status code was: -11
当前ChromeDriver版本:ChromeDriver 129.0.6668.70
解决方案
1. 修正Java命令执行方式
Runtime.exec()不会像shell那样解析DISPLAY=:99这种环境变量赋值语句,换两种方式处理:
方式一:通过shell执行完整命令
把命令交给shell解析,确保环境变量赋值生效:
String comds = "/bin/sh -c 'DISPLAY=:99 python3 test.py 298.html 298.pdf'"; Runtime.getRuntime().exec(comds);
如果是bash环境,也可以用/bin/bash -c ...。
方式二:单独设置环境变量
用exec的重载方法,将DISPLAY加入进程环境:
String[] cmd = {"python3", "test.py", "298.html", "298.pdf"}; // 获取当前环境变量并添加DISPLAY Map<String, String> env = new HashMap<>(System.getenv()); env.put("DISPLAY", ":99"); // 转换为环境变量数组 String[] envArray = env.entrySet().stream() .map(e -> e.getKey() + "=" + e.getValue()) .toArray(String[]::new); // 执行命令 Runtime.getRuntime().exec(cmd, envArray);
2. 给ChromeDriver添加无头模式参数
pyhtml2pdf底层依赖Selenium,Java进程的图形环境可能存在异常,强制开启无头模式可规避这类问题。修改Python脚本,自定义ChromeOptions:
import os import sys from pyhtml2pdf import converter from selenium.webdriver.chrome.options import Options def convert_html_to_pdf(html_path, pdf_path): absolute_html_path = os.path.abspath(html_path) # 配置Chrome无头模式及Linux适配参数 chrome_options = Options() chrome_options.add_argument("--headless=new") chrome_options.add_argument("--no-sandbox") # 解决Linux权限限制 chrome_options.add_argument("--disable-dev-shm-usage") # 避免临时空间不足 # 传入自定义配置 converter.convert(f'file:///{absolute_html_path}', pdf_path, 60, False, 0, False, chrome_options=chrome_options) if __name__ == "__main__": if len(sys.argv) != 3: print("Usage: python3 test.py <html_path> <pdf_path>") else: html_path = sys.argv[1] pdf_path = sys.argv[2] convert_html_to_pdf(html_path, pdf_path)
3. 检查权限与环境一致性
- 确保Java进程有权访问:
Xvfb(若DISPLAY:99是Xvfb实例)、chromedriver、Chrome浏览器、HTML输入文件、PDF输出路径。 - 对比命令行用户与Java进程用户的环境变量,比如
PATH是否包含chromedriver路径,可在Python脚本中打印环境变量排查:import os print(os.environ)
4. 验证Chrome与ChromeDriver版本匹配
确认服务器上Chrome浏览器版本与ChromeDriver主版本号完全一致(比如Chrome 129对应ChromeDriver 129.x)。执行google-chrome --version查看浏览器版本,不匹配则下载对应版本的ChromeDriver替换。
内容的提问来源于stack exchange,提问作者海绵宝宝
相关产品推荐
相关产品推荐

