读取 aws lambda 包中的打包文件
Posted
技术标签:
【中文标题】读取 aws lambda 包中的打包文件【英文标题】:reading a packaged file in aws lambda package 【发布时间】:2017-04-25 02:19:59 【问题描述】:我有一个非常简单的节点 lambda 函数,它读取其中的打包文件的内容。我将代码作为 zip 文件上传。目录结构如下。
index.js
readme.txt
然后在我的 index.js 文件中:
fs.readFile('/var/task/readme.txt', function (err, data)
if (err) throw err;
);
我不断收到以下错误 NOENT: no such file or directory, open '/var/task/readme.txt'.
我也试过 ./readme.txt。
我错过了什么?
【问题讨论】:
听起来文本文件可能没有包含在您的 zip 中,所以我首先会通过从控制台下载 zip 文件来仔细检查。否则,您介意添加更多上下文吗?你的处理函数的其余部分是什么样的? 实际上我正在使用无服务器框架将 zip 文件打包并上传到 S3。我检查了 S3 文件,它确实包含该文件。我要做的是读取 kms 加密数据密钥,以便我的 lambda 可以从 kms 获取加密密钥,以加密对第 3 方的出站 http 调用。 S3 文件是否在您期望的位置包含 txt 文件?此外,如果 serverless 更改了函数的 cwd,则使用像 './readme.txt' 这样的相对路径可能不起作用。也许尝试 __dirname + '/readme.txt' 或者您可以尝试使用 process.cwd() 记录 lambda 函数的 cwd 【参考方案1】:试试这个,它对我有用:
'use strict'
let fs = require("fs");
let path = require("path");
exports.handler = (event, context, callback) =>
// To debug your problem
console.log(path.resolve("./readme.txt"));
// Solution is to use absolute path using `__dirname`
fs.readFile(__dirname +'/readme.txt', function (err, data)
if (err) throw err;
);
;
要调试代码不工作的原因,请在处理程序中添加以下链接
console.log(path.resolve("./readme.txt"));
AWS Lambda 节点进程可能从其他文件夹运行,它会从该文件夹中查找 readme.txt
文件,因为您提供了 relative
路径,解决方案是使用 absolute
路径。
【讨论】:
在使用 Webpack 时使用 __dirname 往往会失败并解析错误的文件夹。在这种情况下,最好使用process.env.LAMBDA_TASK_ROOT
,并根据这个环境变量重建真实路径。
@jaym 如果我使用相同的进程,它会向我抛出找不到文件的错误。在无服务器 Lambda 中获取文件的基本路径是什么?【参考方案2】:
这是一个古老的问题,但在尝试整理 Lambda 上的文件路径时首先出现。
无服务器框架的其他步骤
对于使用无服务器框架进行部署的任何人(可能使用 webpack 构建),您还需要将以下内容添加到您的 webpack 配置文件中(紧跟在 target: node
之后):
// assume target: 'node', is here
node:
__dirname: false,
,
如果没有这篇文章,将 __dirname 与 Serverless 一起使用将仍然无法为您提供所需的绝对目录路径。
【讨论】:
如果你使用 webpack 构建,不用再找了。这是你的答案。【参考方案3】:对我有用的是 Vador 请求使用 process.env.LAMBDA_TASK_ROOT
的 comment。当我在我的机器上使用 __dirname 或在 Lambda 上运行时使用 process.env.LAMBDA_TASK_ROOT
变量在本地运行它时,我编写了一个函数来获取 /templates
目录中的模板文件:
function loadTemplateFile(templateName)
const fileName = `./templates/$templateName`
let resolved
if (process.env.LAMBDA_TASK_ROOT)
resolved = path.resolve(process.env.LAMBDA_TASK_ROOT, fileName)
else
resolved = path.resolve(__dirname, fileName)
console.log(`Loading template at: $resolved`)
try
const data = fs.readFileSync(resolved, 'utf8')
return data
catch (error)
const message = `Could not load template at: $resolved, error: $JSON.stringify(error, null, 2)`
console.error(message)
throw new Error(message)
【讨论】:
【参考方案4】:我使用无服务器框架完成了此操作,它确实是未在压缩中发送的文件。只需在 serverless.yml 中添加以下行:
package:
individually: false
include:
- src/**
【讨论】:
【参考方案5】:const filepath = path.resolve('../../filename.text');
const fileData2 = fs.readFileSync(process.env.LAMBDA_TASK_ROOT + 文件路径, 'utf-8');
【讨论】:
如果您包含您提供的两个代码行的上下文,这将是一个更好的答案。他们应该去哪里? fileData2 应该如何使用?为什么会这样?【参考方案6】:我使用的是fs.promises.readFile()
。无法让它出错。文件就在那里,我觉得 LAMBDA_TASK_ROOT 也是正确的。改成fs.readFileSync()
后,就成功了。
【讨论】:
【参考方案7】:我遇到了同样的问题,我尝试应用上面所有这些出色的解决方案 - 但没有奏效。
问题是我设置了一个文件夹名称,其中一个字母大写,实际上是小写。 所以当我试图获取 /src/SOthing/some_file.txt 的内容时 虽然该文件夹实际上是 /src/Something/ - 我收到了这个错误...
Windows(本地环境)不区分大小写,而 AWS 不区分大小写!!!....
【讨论】:
以上是关于读取 aws lambda 包中的打包文件的主要内容,如果未能解决你的问题,请参考以下文章
打包部署后无法读取jar包里的文件(实测可行,Java中读取jar包中的文件)
使用 AWS Lambda (Python 3) 读取存储在 S3 中的 Parquet 文件