我正在尝试使用打包的R二进制文件和库(不安装)在AWS EC2实例的命令行上运行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
似乎Rscript仍然在默认位置'/usr/lib64/R/bin/R'中寻找R,即使我的R_HOME变量设置为'/home/ec2-user':
ec2-user$ echo $R_HOME
/home/ec2-user
我找到了一些支持,但我找不到任何能解决我具体问题的。有些人建议重新安装R,但我的理解是,为了Lambda的目的,所有东西都需要是自包含的,所以我将R安装在一个单独的EC2实例上,然后将其打包。我应该提到,在安装了R和包管理器的机器上,一切都运行良好。
解决方案:在答案中张贴了我的解决方案。
它认为它就在那里盯着你看:
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并安装它。在一个配置for和安装at路径相同的系统上,一切都很好:
$ Rscript -e "q()" --verbose
running
'/usr/lib/R/bin/R --slave --no-restore -e q()'
$
这篇博文讨论了一个类似的问题,并提供了一个可能的解决方案。我还必须执行这篇文章中的部分解决方案。
我改变了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_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或其他东西,应该比这更容易,所以如果有人有更好的方法,我真的很感激。
另一个更快速的方法:创建相同的文件夹/usr/lib/R/bin/
然后把R放到这个文件夹