Docker容器内Python subprocess调用libreoffice报not found错误
问题根因
你使用的基础镜像python:3.7.7-buster基于Debian 10(Buster)构建,并非CentOS 7,使用apt安装LibreOffice的操作逻辑本身没有问题,但Debian软件源安装的LibreOffice不会自动将可执行文件软链接到全局PATH路径下,实际可执行文件路径为/usr/lib/libreoffice/program/soffice,因此直接调用libreoffice命令会触发/bin/sh: 1: libreoffice: 未找到命令报错。
修复方案
1. 修正Dockerfile配置
不需要安装全量LibreOffice组件,仅安装转换所需的核心组件即可大幅缩减镜像体积,安装完成后手动创建全局软链接保证命令可被全局识别,参考配置如下:
FROM python:3.7.7-buster # 安装转换依赖组件,创建全局命令软链接,清理安装缓存减小镜像体积 RUN apt-get update && apt-get install -y --no-install-recommends \ libreoffice-calc \ libreoffice-writer \ && ln -s /usr/lib/libreoffice/program/soffice /usr/local/bin/libreoffice \ && apt-get clean \ && rm -rf /var/lib/apt/lists/*
如果不想创建软链接,后续调用时直接写绝对路径/usr/lib/libreoffice/program/soffice也可以正常执行。
2. 优化Python调用逻辑
不要使用shell=True拼接命令字符串,这种写法在文件名包含空格、特殊字符时会出现执行异常,还存在命令注入风险,改用列表传参即可规避上述问题,同时加上LibreOffice无头运行的容错参数,规避权限、文件锁相关的报错:
import subprocess # 注意--outdir参数指定转换后文件的输出目录,提前确认目录有写入权限 cmd = [ "libreoffice", "--headless", "--nolockcheck", "--nologo", "--norestore", "--convert-to", "csv", "--outdir", "/tmp", filename ] subprocess.call(cmd)
3. 运行权限注意
- 如果容器内使用非root用户运行Python进程,需要提前给对应用户分配LibreOffice缓存目录(
~/.config/libreoffice)的读写权限,否则会出现启动失败的问题。 - 转换前确认传入的文件路径、输出目录路径都是容器内的真实路径,不要直接挂载宿主机路径后用宿主机的路径规则传参。
验证方式
镜像构建完成后,先进入容器执行which libreoffice,如果返回路径/usr/local/bin/libreoffice说明命令软链接配置正常,再手动执行一次文件转换命令验证功能正常,再启动业务服务即可。
内容的提问来源于stack exchange,提问作者Petar Petrovic
相关产品推荐
相关产品推荐

