【问题标题】:How can I get my AWS Lambda to access gems stored in vendor/bundle?如何让我的 AWS Lambda 访问存储在供应商/捆绑包中的 gem?
【发布时间】:2018-12-05 14:12:49
【问题描述】:

我正在用 Ruby 编写一个 Lambda 函数,它最终会通过 Webhook 在 Slack 中向我发送一些通知。所以我的lambda_function 文件是

require 'json'
require 'webhook'

def lambda_handler(event:, context:)
    # TODO implement
    { statusCode: 200, body: JSON.generate('Hello from Lambda!') }
    Webhook.post('https://mywebhookurl', {message: 'test'})
end

我的内联代码编辑器中的目录结构如下所示:

Gemfile
Gemfile.lock
lambda_function.rb
vendor/
  bundle/
    ruby
      2.3.0
        gems/webhook

2.3.0 浴下还有其他几个文件夹,包括build_infocachedoc 等。为了将此代码放到 AWS Lambda 上,我正在运行

zip -r myLambda.zip * 将所有内容放入一个 zip 文件并上传到 Lambda。

但是,当我最终在 lambda 上运行基本测试时,我收到以下错误:

{
  "errorMessage": "cannot load such file -- webhook",
  "errorType": "Init<LoadError>",
  "stackTrace": [
    "/var/lang/lib/ruby/2.5.0/rubygems/core_ext/kernel_require.rb:59:in `require'",
    "/var/lang/lib/ruby/2.5.0/rubygems/core_ext/kernel_require.rb:59:in `require'",
    "/var/task/lambda_function.rb:2:in `<top (required)>'",
    "/var/lang/lib/ruby/2.5.0/rubygems/core_ext/kernel_require.rb:59:in `require'",
    "/var/lang/lib/ruby/2.5.0/rubygems/core_ext/kernel_require.rb:59:in `require'"
  ]
}

不应该再有这个了,因为following tutorial 准确地显示了如何设置我拥有的东西,但它不起作用。有没有人成功地从 AWS Lambda 中的 gemfile 中提取 gem?

【问题讨论】:

  • 你捆绑在 2.3.0 下并且在 2.5.0 下运行,这可能是一个很好的起点

标签: ruby amazon-web-services aws-lambda bundler


【解决方案1】:

我在使用 Ruby 构建 AWS Lambda 层时遇到了同样的问题。一种快速简便的方法是将所有 gem 路径添加到 AWS Lambda 中的 Ruby 的 $LOAD_PATH。即:

load_paths = Dir["/opt/ruby/gems/2.5.0/**/lib"]
$LOAD_PATH.unshift(*load_paths)

require 'webhook'

在您的情况下将"/opt/ruby/gems/2.5.0/**/lib" 替换为"./vendor/bundle/ruby/2.3.0/gems/**/lib"

当您执行require 'webhook' 时,它将遍历所有路径并遇到"./vendor/bundle/ruby/2.3.0/gems/webhook-1.0.0/lib/webhook.rb" 并将其添加到您的AWS Lambda 中。 require 不需要文件扩展名。

当我们通过 bundler 运行 rails 时,它为我们做了很多“魔术”,包括确保我们的 $LOAD_PATH 指向 gems。由于 AWS Lambda 不使用捆绑程序,因此我们需要自己做一些这种“魔术”。

【讨论】:

  • 我在尝试使用来自 GitHub(master 分支)的 gem 时遇到了类似的问题。看来我的宝石的路径不一样,它在:./vendor/bundle/ruby/2.5.0/bundler/gems/。这意味着我必须调整这两行,使其看起来像这样:load_paths = Dir["./vendor/bundle/ruby/2.5.0/bundler/gems/**/lib"]。我不知道这是否有区别:我使用的是bundler 2.0.1 版。
  • 我需要这个 AND 2.3 -> 2.5 答案。
  • 对于那些寻找简单示例的人,您可以在这里找到:github.com/ryanjones/ruby_lambda_layers
【解决方案2】:

您需要确保您在本地用于捆绑的 Ruby 版本与 Lambda 使用的版本相匹配。

您的 zip 似乎已在 2.3.0 中安装了 gem,但您的堆栈跟踪列出了 2.5.0。这种不匹配意味着 lambda runner 找不到你的 gem。

【讨论】:

    【解决方案3】:

    我认为您不应该更改 GEM_PATH 或必须在每个 lambda 函数中设置 $LOAD_PATH。 “最好”的方法是在创建图层存档时做这个小技巧:

    bundle install --path vendor/bundle
    cd vendor/bundle
    mkdir ruby/gems
    mv ruby/2.5.0 ruby/gems/
    zip -r layer.zip ruby/gems/2.5.0/
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-05-20
      • 2014-12-03
      • 2014-04-15
      • 1970-01-01
      • 2016-10-30
      • 2023-03-23
      • 1970-01-01
      • 2018-05-04
      相关资源
      最近更新 更多