node.js - NodeJs : Exiftool can not be spawned in AWS Lambda environment

标签 node.js amazon-web-services 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) 

请帮我解决这个问题。

谢谢。

最佳答案

错误消息相当具有误导性,但有一些提示。路径为 /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() 的 shell 命令。因此,我们必须确保通过执行以下操作来处理它:

exiftool.open({ shell: true })

此时您可能已完成,或者可能会遇到以下错误: perl:加载共享库时出错:libcrypt.so.1:无法打开共享对象文件:没有这样的文件或目录。我不确定如何最好地解决这个问题。也许自己编译 Perl 并自己创建一个层可以防止这种情况发生。但对我有用的快速而肮脏的解决方案是从本地 ubuntu 系统复制 libcrypt.so.1 文件 ($ whereis libcrypt.so.1),将其放入放入名为 lib 的文件夹中,压缩该文件夹并将其作为新层上传。

关于node.js - NodeJs : Exiftool can not be spawned in AWS Lambda environment,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58932115/

相关文章:

python - 如何在某些后缀的s3中从一个桶复制到另一个桶

aws-lambda - AWS Lambda Authorizer `body` 对象中不存在 `event` 参数

amazon-web-services - 使用 Cognito 防止多个同时登录

javascript - react native - 在 package.json 中使用别名进行绝对导入

javascript - 如何使用 puppeteer 从网站获取所有链接

amazon-web-services - elb健康检查和ec2健康检查有什么区别?

javascript - 急速模块命名冲突 : react native app with AWS Service (Amplify Project)

javascript - 在 Angular 中,一个组件如何拥有多个 HTML 模板?

node.js - Socket.io 使用默认命名空间和一些自定义命名空间,不起作用

linux - EC2 实例, "General error mounting filesystems"