index.php
:
<?php
echo exec("Rscript foo.R");
?>
foo.R
:
#!/usr/bin/env Rscript
print("Before!")
#library(rJava);
print("After!");
网页上的输出:
[1] "After!"
现在这是预期的输出,因为exec
返回命令结果的最后一行。
现在,因为我想访问需要rJava
和RMongo
库的mongodb数据库,所以我修改了上面的代码。
foo.R
:
#!/usr/bin/env Rscript
print("Before!")
library(rJava);
print("After!");
网页上的输出:
[1] "Before!"
现在我不明白这个输出。我期望与之前相同的输出,即[1] "After!"
。好像从库导入行开始的R代码根本不存在。我已经在kmeans
中测试了上面的代码(以及我对从mongodb
抓取的数据使用R shell
时省略的代码),它按预期工作。
在R
脚本中导入库时出现了什么问题,该脚本是从PHP
执行的?
更新1 :
有趣的是,如果我从命令行调用foo.R
,则会根据我的期望调用并执行修改后的index.php
。
$ php index.php
Loading required package: methods
[1] "After!"
所以我的结论是我的普通用户帐户可以执行index.php
,而foo.R
可以加载www-data
中的库,但似乎R
用户帐户没有权限加载www-data
中的库1}}。
现在问题是如何授予R
加载www-data
库的权限?
更新2 :
我通过将apache用户从if
更改为我当前的用户来暂时解决了这个问题,但我知道这是一个巨大的安全风险,我正在寻找替代解决方案。
答案 0 :(得分:3)
首先,当www-user无法加载R库时,您应该确切地检查Apache日志中出现的错误。最可能的两个罪魁祸首是权限错误和库搜索路径不正确。
如果为本地用户而不是系统范围安装库,则www-data
将无法找到它们,但Apache日志中的错误应显示此信息。
答案 1 :(得分:0)
另一种选择可能是您不使用PHP直接执行R脚本。
您可以使用像Redis
这样的键值数据库或像Rabbitmq
这样的排队系统。而不是直接执行脚本,而是向这些系统中的任何一个发送消息。
在命令行中执行php脚本,轮询其中任何一个系统以查找任何新消息,当它收到消息时,它会执行脚本并使用脚本的结果作出响应。
所以它将成为一个双向消息传递系统:
Script A ----> Queue ----> Script B ----> R Script
R Script --result--> Script B ----> Queue ----> Script A
这是一个初期实施但有点安全和可扩展的系统。
我建议你看一下Celery。