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