我正在尝试创建一个运行时层,以使其能够使用new runtime API将R用作lambda函数的运行时。
为此,我创建了一个包含R所需的所有依赖项的层,然后创建了一个包含R本身的第二层。我使用运行lambda的同一Amazon AMI构建了这些层。我通过压缩各层,创建一个新实例,然后将各层下载并解压缩到该新实例中来测试我的构建(将所有内容放入/ opt,这也恰好是我在构建R及其依赖项时在其中安装的地方) 。我使用了最少资源(2个CPU,4GB RAM)的实例类型。据我了解,这应该非常接近lambda环境。
我有一个小的测试脚本(test.r),它只是将一条消息打印到stdout。 这在测试环境中运行良好。这是脚本:
cat("hello from planet lambdar")
这是在我的层的引导脚本中调用它的方式:
SCRIPT=$LAMBDA_TASK_ROOT/$(echo "$_HANDLER" | cut -d. -f1).r
echo "About to run $SCRIPT"
/opt/R/bin/Rscript $SCRIPT
从下面的日志记录中可以明显看出,脚本的名称已正确发送和解析。我以前已经确认脚本test.r可以按预期方式放在/ var / task中。但是通过lambda运行此脚本会导致分段错误:
START RequestId: 2c1b8801-f903-11e8-a32d-796c039278f1 Version: $LATEST
About to run /var/task/test.r
/opt/bootstrap: line 18: 18 Segmentation fault (core dumped) /opt/R/bin/Rscript $SCRIPT
鉴于该过程在最小的EC2实例上运行正常,该实例运行lambda使用的同一Amazon AMI,并加载了与我为我添加到lambda的层创建的相同的工具和依赖项集,因此该方法如何调试此分段错误功能?
答案 0 :(得分:4)
在这种情况下,事实证明,我过于主动地将链接到R可执行文件的共享库复制到我的层中。我按了
列出的所有内容ldd /opt/R/lib/libR.so
并将其复制到/ opt / lib
问题在于,这些库中有许多已经在AMI中,并且它们存在于不同位置会引起问题(也许与库缓存有关?)。
通过仅移动不在AMI中的两个库(但是在安装构建工具时添加了这些库,这些库当然不在Lambda环境中),segfault消失了。这两个库是:
/usr/lib64/libgfortran.so.3
/usr/lib64/libquadmath.so.0
要在此处回答更深层的问题,即如何在Lambda环境中调试段错误,我发现了灵感here,并在我的bootstrap
脚本中包含了以下内容:从核心转储中打印回溯:
gdb -q -n -ex bt -batch /opt/R/bin/Rscript /temp/core.N.XXXX
其中core.N.XXXX是核心转储文件的名称(可以通过将echo $(ls /tmp)
放在bootstrap
脚本中来发现)。然后,cloudwatch日志将至少包含回溯中的一些提示。