Django项目中wkhtmltopdf返回非零退出状态1/Apache下为6求助
我来帮你一步步分析和解决这个问题,先从两个不同环境的错误码入手:
一、开发环境退出码1的排查
退出码1通常是wkhtmltopdf执行时遇到了基础执行错误,比如命令参数错误、模板渲染问题或资源加载失败,你可以按以下步骤排查:
修正错误的命令参数
看你报错里的命令:['wkhtmltopdf', '--disable-javascript', '--encoding', u'utf8', '--quiet', u'False', '/tmp/wkhtmltopdfnUwu3t.html', '-']
这里的--quiet是wkhtmltopdf的布尔开关参数,不需要传值u'False'——如果要关闭安静模式,直接移除这个参数即可;如果要开启,只写--quiet就行。这个参数格式错误很可能是导致退出码1的直接原因。手动测试PDF生成
把临时HTML文件(比如/tmp/wkhtmltopdfnUwu3t.html)复制出来,直接在命令行执行wkhtmltopdf命令,看具体报错信息:wkhtmltopdf --disable-javascript --encoding utf8 /tmp/wkhtmltopdfnUwu3t.html test.pdf这样能直观看到问题:比如模板里的CSS/图片路径不对、HTML语法错误、字体缺失等。
检查模板资源路径
确保pdf/test.html里的静态资源(CSS、图片)使用绝对路径,或者能被wkhtmltopdf访问到——开发环境中如果用相对路径,wkhtmltopdf可能找不到这些资源,导致生成失败。升级wkhtmltopdf版本
旧版本的wkhtmltopdf可能有兼容性问题,试试升级到最新的稳定版,能解决不少已知的渲染bug。
二、Apache部署环境退出码6的排查
退出码6在Apache环境下,大多和权限、系统依赖或无显示服务有关,按以下步骤处理:
检查Apache用户权限
Apache通常以www-data用户运行,你需要确保这个用户有:- 访问Django模板、静态文件的权限
- 读写临时目录(
/tmp)的权限
可以先测试让www-data执行基础的wkhtmltopdf命令:
sudo -u www-data wkhtmltopdf http://google.com test.pdf如果报错,说明权限或依赖有问题。
安装缺失的系统依赖
wkhtmltopdf依赖很多系统库,生产环境经常会缺失,以Debian/Ubuntu为例,执行以下命令安装:sudo apt-get install libxrender1 libfontconfig1 libx11-dev libjpeg62-turbo libpng16-16 xvfb解决无X11环境的问题
wkhtmltopdf基于WebKit,需要X11显示环境,但生产服务器一般没有桌面。你可以用xvfb模拟显示环境,修改Django设置:# settings.py中添加 WKHTMLTOPDF_CMD = 'xvfb-run wkhtmltopdf'或者在命令参数中添加
--no-sandbox(注意:这个参数有安全风险,仅在可信环境使用)。自定义临时文件目录
如果/tmp目录权限有问题,可以在视图中指定自定义临时目录,确保Apache用户能读写:class MyPDF(OrgOwnerMixin, PDFTemplateView): # 其他配置... temp_directory = '/path/to/writable/tmp' # 替换为Apache有权限的目录
三、你的视图代码优化建议
针对你的MyPDF视图,有两个小优化点:
- 用
get_object_or_404替代直接get,避免找不到组织时抛出500错误:from django.shortcuts import get_object_or_404 def get_object(self, *args, **kwargs): return get_object_or_404(Organisation, slug=self.kwargs['slug']) - 自定义命令参数,避免默认参数出错:
def get_cmd_options(self): options = super().get_cmd_options() # 移除错误的--quiet参数 options.pop('--quiet', None) # 明确设置需要的参数 options.update({ '--encoding': 'utf-8', '--disable-javascript': True, }) return options
先解决开发环境的问题,确保本地能正常生成PDF后,再部署到Apache环境处理权限和依赖问题,应该就能解决了。
内容的提问来源于stack exchange,提问作者HenryM

