AWS Lambda 的打包 R 在使用 Rscript 时无法工作

3
我正在尝试在 AWS EC2 实例的命令行上使用已打包的 R 二进制文件和库(无需安装)运行 R 脚本,以测试用于部署到 AWS Lambda 的脚本。我遵循了这些说明。该指南是为了将所有 R 二进制文件和库打包到一个 zip 文件中,并将所有内容移动到 Amazon EC2 实例进行测试。我在新机器上解压了所有内容,在机器上运行了 'sudo yum update' 命令,并设置了 R 的环境变量以指向正确的位置:
export R_HOME=$HOME
export LD_LIBRARY_PATH=$HOME/lib

注意:$ HOME 等于 / home/ec2-user。

我创建了这个 hello_world.R 文件进行测试:

#!/home/ec2-user/bin/Rscript
print ("Hello World!")

但是当我运行了这个命令:
ec2-user$ Rscript hello_world.R

我得到了以下错误:
Rscript execution error: No such file or directory

所以我检查了路径,但是一切都没问题:

ec2-user$ whereis Rscript
  Rscript: /home/ec2-user/bin/Rscript

ec2-user$ whereis R
  R: /home/ec2-user/bin/R /home/ec2-user/R

但是当我尝试在命令行使用Rscript评估一个表达式时,我得到了以下结果:

ec2-user$ Rscript -e "" --verbose
  running
    '/usr/lib64/R/bin/R --slave --no-restore -e '

  Rscript execution error: No such file or directory

尽管我已将R_HOME变量设置为“/home/ec2-user”,但似乎Rscript仍在寻找默认位置“/usr/lib64/R/bin/R”中的R:

ec2-user$ echo $R_HOME
  /home/ec2-user

我找到了一些支持,但找不到任何针对我的特定问题的解决方案。有些人建议重新安装R,但据我了解,为了Lambda的目的,一切都需要自包含,所以我在一个单独的EC2实例上安装了R,然后将其打包起来。值得一提的是,在使用软件包管理器安装R的机器上,一切都运行良好。
解决方案: 在答案中发布了我的解决方案
3个回答

4

它认为它就在那儿盯着你:

ec2-user$ whereis R
  R: /home/ec2-user/bin/R /home/ec2-user/R

这是您放置R代码的位置 -- 然而,它是为此构建的/期望此项内容:

ec2-user$ Rscript -e "" --verbose
  running
    '/usr/lib64/R/bin/R --slave --no-restore -e '

这些路径并不相同。真正的错误可能是你假设只需将已经安装和配置好的R安装程序移动到另一个目录中即可。但事实并非如此。

你可以为新路径构建R并进行安装。在已经配置和安装路径相同的系统上,一切都很顺利:

$ Rscript -e "q()" --verbose
running
  '/usr/lib/R/bin/R --slave --no-restore -e q()'

$ 

谢谢。是的,我感觉这是问题的根源,但不确定如何解决。最终,我遵循了这个解决方案的一部分:http://fumodibit.blogspot.co.uk/2013/04/modifying-r-to-obtain-relocatable.html?showComment=1436450064627 - Rafaan Anvari
感谢提供信息。在调试过程中,我按照评论中的链接进行操作,并通过设置RHOME环境变量为R主目录(export RHOME=$R_HOME_DIR)解决了这个问题。 - ialm

3

这篇博客介绍了类似的问题,并提供了一个潜在的解决方案。我还不得不从这篇文章中实现部分解决方案。

我修改了R源代码的第一行,将其改为:

#!/bin/sh
# Shell wrapper for R executable.

R_HOME_DIR=${R_ROOT_DIR}/lib64${R_ROOT_DIR}

到这个:
R_HOME_DIR=${RHOME}/lib64${R_ROOT_DIR}

我会在下面解释原因。
注意--其余代码为:
if test "${R_HOME_DIR}" = "${R_ROOT_DIR}/lib64${R_ROOT_DIR}"; then
   case "linux-gnu" in
   linux*)
     run_arch=`uname -m`
     case "$run_arch" in
        x86_64|mips64|ppc64|powerpc64|sparc64|s390x)
          libnn=lib64
          libnn_fallback=lib
        ;;
        *)
          libnn=lib
          libnn_fallback=lib64
        ;;
     esac
     if [ -x "${R_ROOT_DIR}/${libnn}${R_ROOT_DIR}/bin/exec${R_ROOT_DIR}" ]; then
        R_HOME_DIR="${R_ROOT_DIR}/${libnn}${R_ROOT_DIR}"
     elif [ -x "${R_ROOT_DIR}/${libnn_fallback}${R_ROOT_DIR}/bin/exec${R_ROOT_DIR}" ]; then
        R_HOME_DIR="${R_ROOT_DIR}/${libnn_fallback}${R_ROOT_DIR}"
     ## else -- leave alone (might be a sub-arch)
     fi
     ;;
  esac
fi

if test -n "${R_HOME}" && \
   test "${R_HOME}" != "${R_HOME_DIR}"; then
  echo "WARNING: ignoring environment value of R_HOME"
fi
R_HOME="${R_HOME_DIR}"
export R_HOME

你可以在底部看到,该代码将R_HOME设置为R_HOME_DIR,而R_HOME_DIR最初是基于R_ROOT_DIR分配的。
无论您将R_HOME_DIR或R_HOME变量设置为什么,R都会使用R_ROOT_DIR变量重置所有内容。
有了这个更改,我可以设置所有环境变量:
export RHOME=$PWD/R  #/home/ec2-user/R
export R_HOME=$PWD/R #/home/ec2-user/R
export R_ROOT_DIR=/R #/R

我将RHOME设置为我的工作目录,其中包含R软件包。在我的情况下,RHOME基本上充当一个前缀,它是/home/ec2-user/。
此外,Rscript将/R/bin添加到任何RHOME中,因此现在我可以正确地运行...
Rscript hello_world.R

...在命令行上运行。Rscript知道如何找到R,而R知道如何找到所有它的东西。

我觉得将R打包成可移植的自包含文件夹应该比这更容易,而不使用Docker或其他工具,如果有人有更好的方法,请告诉我,我会非常感激。


0
另一个更快的方法: 创建相同的文件夹 /usr/lib/R/bin/ 然后将 R 放入此文件夹中。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接