You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于shelf/lambda-libreoffice-base镜像的Lambda文档转PDF间歇性故障求助

问题:AWS Lambda中LibreOffice转PDF间歇性报错(JRE未找到/线程创建失败)

现象

基于shelf/lambda-libreoffice-base:7.4-node16-x86_64构建自定义Docker镜像,实现Word转PDF功能,大部分时间正常,但间歇性出现以下错误:

  • javaldx: Could not find a Java Runtime Environment!
  • terminate called after throwing an instance of 'std::runtime_error'
  • what(): osl::Thread::create failed
    重新部署镜像后可恢复正常,但一段时间后会再次复发。

相关代码

Dockerfile

FROM public.ecr.aws/shelf/lambda-libreoffice-base:7.4-node16-x86_64

COPY ./fonts/* /usr/local/share/fonts/
COPY ./ ./
RUN yum install java-1.8.0-openjdk-devel -y
CMD [ "app.handler" ]

Lambda处理函数

const handler = async (event) => {
  try {
    const {fileUrl, isExcel} = event;

    const inputFileExtension = ".docx";
    const fileName = `template-${uuidv4()}${inputFileExtension}`;
    await download(fileUrl, `/tmp/${fileName}`);
    const pdfFilePath = convertTo(fileName, 'pdf');
    const stats = fs.statSync(pdfFilePath);
    const pdfFileData = fs.readFileSync(pdfFilePath);
  
    await clearTmpDirectory();
    const response = {
      statusCode: 200,
      body: pdfFileData
    };
    return response;
  } catch (err) {
    console.error(err);
    throw err;
  }
}

报错日志

javaldx: Could not find a Java Runtime Environment!

what():  osl::Thread::create failed

terminate called after throwing an instance of 'std::runtime_error'

Error: Command failed: cd /tmp && libreoffice7.4 --headless --invisible --nodefault --view --nolockcheck --nologo --norestore --convert-to pdf --outdir /tmp /tmp/template-bf853fb4-95d9-4fef-87b1-59c54cf13c58.docx
javaldx: Could not find a Java Runtime Environment!
Warning: failed to read path from javaldx
terminate called after throwing an instance of 'std::runtime_error'
  what():  osl::Thread::create failed

    at checkExecSyncError (node:child_process:861:11)
    at execSync (node:child_process:932:15)
    at convertTo (/var/task/node_modules/@shelf/aws-lambda-libreoffice/lib/convert.js:29:40)
    at Runtime.handler (/var/task/app.js:66:25) {
  status: 134,
  signal: null,
  output: [
    null,
    <Buffer >,
    <Buffer 6a 61 76 61 6c 64 78 3a 20 43 6f 75 6c 64 20 6e 6f 74 20 66 69 6e 64 20 61 20 4a 61 76 61 20 52 75 6e 74 69 6d 65 20 45 6e 76 69 72 6f 6e 6d 65 6e 74 ... 150 more bytes>
  ],
  pid: 12370,
  stdout: <Buffer >,
  stderr: <Buffer 6a 61 76 61 6c 64 78 3a 20 43 6f 75 6c 64 20 6e 6f 74 20 66 69 6e 64 20 61 20 4a 61 76 61 20 52 75 6e 74 69 6d 65 20 45 6e 76 69 72 6f 6e 6d 65 6e 74 ... 150 more bytes>
}

核心原因

  1. Lambda容器复用机制:Lambda会复用之前的执行环境,导致LibreOffice进程残留、环境变量丢失或资源耗尽
  2. Java环境变量未持久化:仅安装JDK但未全局配置JAVA_HOME和PATH,复用容器时javaldx无法找到JRE
  3. 资源不足:Lambda默认内存/文件句柄限制过低,导致LibreOffice无法创建新线程
  4. 临时目录清理不当:清空/tmp目录时误删LibreOffice必要临时文件,或未终止残留进程

解决方案

1. 全局配置Java环境变量

修改Dockerfile,用ENV指令持久化JRE路径,避免容器复用时丢失:

FROM public.ecr.aws/shelf/lambda-libreoffice-base:7.4-node16-x86_64

COPY ./fonts/* /usr/local/share/fonts/
COPY ./ ./
RUN yum install java-1.8.0-openjdk-devel -y
# 全局配置Java环境变量
ENV JAVA_HOME=/usr/lib/jvm/java-1.8.0-openjdk
ENV PATH=$JAVA_HOME/bin:$PATH
CMD [ "app.handler" ]

2. 禁用LibreOffice的Java依赖

Word转PDF无需Java支持,直接在启动参数中添加--disable-java跳过JRE检查:

// 替换原有convertTo调用,手动构造命令
const { execSync } = require('child_process');
const convertTo = (fileName, format) => {
  const inputPath = `/tmp/${fileName}`;
  const outputDir = '/tmp';
  execSync(`libreoffice7.4 --headless --invisible --nodefault --view --nolockcheck --nologo --norestore --disable-java --convert-to ${format} --outdir ${outputDir} ${inputPath}`);
  return `${outputDir}/${fileName.replace(/\.[^/.]+$/, `.${format}`)}`;
};

3. 优化临时目录清理逻辑

不要清空整个/tmp,仅删除自身生成的文件,清理前先终止LibreOffice残留进程:

const clearTmpDirectory = async () => {
  // 终止所有LibreOffice进程
  execSync('pkill -f libreoffice7.4 || true');
  // 仅删除自己生成的template开头的文件
  const files = await fs.promises.readdir('/tmp');
  for (const file of files) {
    if (file.startsWith('template-')) {
      await fs.promises.unlink(`/tmp/${file}`);
    }
  }
};

4. 强制设置环境变量(应对容器复用)

在handler开头强制注入环境变量,确保每次执行都有正确的JRE路径:

const handler = async (event) => {
  // 强制设置Java环境变量,避免容器复用丢失
  process.env.JAVA_HOME = '/usr/lib/jvm/java-1.8.0-openjdk';
  process.env.PATH = `${process.env.JAVA_HOME}/bin:${process.env.PATH}`;
  
  // 原有逻辑...
}

5. 提升Lambda资源配置

将Lambda内存配置从默认256MB提升至512MB或1GB,同时提高文件句柄限制(通过/etc/security/limits.conf在Dockerfile中配置):

RUN echo "* soft nofile 65536" >> /etc/security/limits.conf && \
    echo "* hard nofile 65536" >> /etc/security/limits.conf

内容的提问来源于stack exchange,提问作者Tanmay Agarwal

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 08:30:10