NodeJ:无法在AWS Lambda环境中生成Exiftool

时间:2019-11-19 10:40:51

标签: node.js amazon-web-services aws-lambda exiftool

无法在AWS Lambda环境中生成Exiftool,并出现以下错误:

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) 

请帮助我解决此问题。

谢谢。

1 个答案:

答案 0 :(得分:2)

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

实际上缺少的是一个Perl二进制文件

AWS显然从运行时环境中删除了各种二进制文件。现在看来,最佳实践是使用“图层”添加缺少的依赖项。

因此,首先,将perl作为图层添加到您的AWS Lambda函数中,以使用来自https://metacpan.org/pod/AWS::Lambda的ARN。然后,应该在/opt/bin/perl处获得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()的shell命令。因此,我们必须通过执行以下操作来确保对它进行处理:

exiftool.open({ shell: true })

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