我正在尝试从PHP运行R脚本,并在R脚本中,我将创建test.jpg图像,并在PHP中,我将在web上显示此图像。
R是2.11.1,OS是ubuntu10.10
问题是:如果我从终端运行,这个。jpg创建成功,但如果我从web运行,没有创建图像。我在同一目录下从终端和web运行脚本。/opt/lampp/根/名称/。如果有人能告诉我一个好的工具来调试这个web,那就太好了。我在。php文件中放了一些echo,我看到函数被调用,但仍然不知道如何解决这个bug)。
.jpg是在我从终端运行时创建的:
php r_caller.php
在这个r_caller.php中,我有一个简单的函数:
<?php php_call_r(){
$cmd = "echo 'argv <- '"r_command.r'"; source(argv)' | " .
"/usr/bin/R --vanilla --slave";
$ret = system($cmd);
echo $ret;}
?>
和这个php_call_r函数在与r_caller.php相同的文件中调用:
<?php
//some irrelavant codes above
php_call_r();
print("<img src=test.jpg>");
?}
和r_command。在r脚本中,我有简单的命令:
jpeg("test.jpg")
plot(50, 50)
dev.off()
我真的很感谢你的帮助! 您没有指定您的平台和R版本,但是在unix上jpeg()
设备可能需要X11来呈现图像(您可能在交互式会话中有,但在apache中没有)。您最好使用Cairo
包或其他不需要X11会话的方法(最近的R允许您在jpeg
调用中使用替代类型,您也可以尝试-参见?jpeg
)。
(顺便说一句,有一个PHP客户端可以使web请求更快-运行R本身几乎是PHP中最慢的使用R的方式。如果您不想安装任何软件包,那么您可能需要至少使用Rscript
)
还有一件事要考虑,检查你的文件权限-确保www-data
有写权限,无论你将在哪里创建文件(例如,查看echo system("pwd");
当前目录R将运行)。
检查Apache错误日志,看看是否有错误。尝试在PHP代码的开头添加以下内容:
error_reporting(E_ALL);
ini_set('display_errors','On');
这可能是一个复制/粘贴错误,但是您的php_call_r函数没有正确地定义为函数。我的建议如下:
<?php function php_call_r() {
$cmd = "echo 'argv <- '"r_command.r'"; source(argv)' | " .
"/usr/bin/R --vanilla --slave";
$ret = system($cmd);
echo $ret;
}
?>
对每个请求从PHP执行R是一个非常糟糕的主意——PHP管道通常不可靠,R的输出是为交互式工作而优化的,而不是传输结果。而且R的启动时间很长,所以你浪费了大量的时间和CPU功率。
更好的方法是使用R worker守护进程,由Rserve或trigger创建——Rserve有PHP客户端,对于trigger,你需要自己编写一个,但这是微不足道的;它可能看起来像这样:
R部分(r.R)
require(triggr);
serve(function(data_from_php){
cat(sprintf("Called with: %s'n",data_from_php));
#<<Picture creation code>>
#Break connection notifying PHP that picture is done
return(endConnection("Done'r'n"));
},9090);
# ^- Port you want to use for internal communication
PHP部分<?php
$s=socket_create(AF_INET,SOCK_STREAM,SOL_TCP);
echo "Connecting...'n";
if(socket_connect($s,"localhost",9090)){
echo "Connected!'n"; //v double 'r'n is crucial
$d="some data for R'r'n'r'n";
socket_write($s,$d,strlen($d));
//This blocks until picture is done
$r=socket_read($s,6);
//Here we can emit the page featuring <img>
echo "Response was $r'n";
}
?>
现在你只要在后台或在一些自动复活守护程序下启动r.R
,你就完成了。