首页 > 解决方案 > NodeJs:无法在 AWS Lambda 环境中生成 Exiftool

问题描述

Exiftool 无法在 aws lambda 环境中生成,出现以下错误:

ERROR   { Error: spawn /var/task/node_modules/dist-exiftool/node_modules/exiftool.pl/vendor/exiftool ENOENT
at Process.ChildProcess._handle.onexit (internal/child_process.js:240:19)
at onErrorNT (internal/child_process.js:415:16)
at process._tickCallback (internal/process/next_tick.js:63:19)
errno: 'ENOENT',
code: 'ENOENT',
  syscall:
   'spawn /var/task/node_modules/dist-exiftool/node_modules/exiftool.pl/vendor/exiftool',
  path:
   '/var/task/node_modules/dist-exiftool/node_modules/exiftool.pl/vendor/exiftool',
  spawnargs:
   [ '-echo2', '1574158488325', '-stay_open', 'True', '-@', '-' ] }

一个函数在 AWS Lamda 上与 NodeJs 8.10 版一起正常工作,但我想将此函数升级到 NodeJs 10.X 版。我未能在 NodeJs 10.X 上运行函数。我总是在以下行出现错误。

const ep = new exiftool.ExiftoolProcess(exiftoolBin);

我的功能:

const exiftool =  require('node-exiftool')
const exiftoolBin = require('dist-exiftool')

const fs = require('fs')
const path = require('path')

const ep = new exiftool.ExiftoolProcess(exiftoolBin)

const PHOTO_PATH = path.join(__dirname, 'photo.jpg')
const rs = fs.createReadStream(PHOTO_PATH)

ep.open()
    .then(() => ep.readMetadata(rs, ['-File:all']))
    .then((res) => {
        console.log(res)
    })
    .then(() => ep.close(), () => ep.close())
    .catch(console.error) 

请帮我解决这个问题。

谢谢你。

标签: node.jsamazon-web-servicesaws-lambdaexiftool

解决方案


错误消息相当具有误导性,但有一些提示。路径说/exiftool.pl/pl 通常是 perl。如果您打开 exiftool 文件,您将#!/usr/bin/perl -w在第一行看到。

实际缺少的(ENOENT)是一个 perl 二进制文件

AWS 显然从运行时环境中删除了各种二进制文件。现在看来最好的做法是使用层来添加缺失的依赖项。

因此,首先,将 perl 作为层添加到您的 AWS Lambda 函数中,为此您可以使用来自https://metacpan.org/pod/AWS::Lambda的 ARN 。然后 perl 二进制文件应该可以在/opt/bin/perl,它与 #! 不匹配。的脚本,所以我们要调整功能代码:

const { ExiftoolProcess } = require('node-exiftool');
const exiftoolBin = require('dist-exiftool');

// Get perl binary path from environment variables or fallback to default.
const perlBin = process.env.PERL_BIN || '/opt/bin/perl';
// Instead of calling the perl script directly causing #! to choose the
// interpreter path, we'll pass the script path to the interpreter directly. 
const exiftool = new ExiftoolProcess(`${perlBin} ${exiftoolBin}`);

但是现在传递给的路径ExiftoolProcess不再是有效的文件路径。这是一个传递给child_process.spawn(). 因此,我们必须确保通过以下方式处理它:

exiftool.open({ shell: true })

此时您可能已完成,或者您可能会遇到以下错误: perl: error while loading shared libraries: libcrypt.so.1: cannot open shared object file: No such file or directory. 我不确定如何最好地解决这个问题。也许自己编译 perl 并自己创建一个层可以防止它。但是对我有用的快速而肮脏的解决方案是libcrypt.so.1从我的本地 ubuntu 系统 ( $ whereis libcrypt.so.1) 复制文件,将其放入名为 的文件夹lib中,压缩该文件夹并将其作为新层上传。


推荐阅读