如何通过PHP (gearman) worker运行时返回R程序状态


How to return R program status when run via PHP (gearman) worker?

我有一个PHP脚本(worker in gearman),调用Rscript(带状态进度条),运行良好,但我不知道程序的状态。我的问题,如果它是可能的rscript返回运行状态回到php脚本。

<?php
print_r(posix_getpwuid(getmyuid()));
print_r(pathinfo($YOUR_PATH));
exec(" RScript ~/dynamic.R 'select field1, field2 from table where 1=1 limit 100' ");
?>

动态。R执行一些数据操作的100行(我有plyr函数与进度条),但与gearman的进度条不显示,因此希望在gearman中显示进度。

希望我的问题有意义

Regards, Savi

如果您重定向输出,然后从文件中读取输出,理论上可以对exec()执行此操作,但是如果不首先找到其PID,则几乎不可能与进程协调。这就是proc_open()的作用。popen()可能工作,但我猜进度条被写入stderr,这就是我在这里为你模拟的。

这里有一个小程序,对你来说应该是一个工作的例子:

<?php
$descriptors = array(
    0 => array("pipe", "r"),
    1 => array("pipe", "w"),
    2 => array("pipe", "w")
);
$process = proc_open( "/usr/bin/env ruby ./rlike.rb 1 10", $descriptors, $pipes, getcwd() );
if( is_resource($process) ){
    echo "ran process'n";
    do{
        $status = proc_get_status($process);
        if(! $status["running"]) break;
        fflush($pipes[2]);
        $progressbar = fread( $pipes[2],1 );
        if( $progressbar == "'r" ) echo "'n";
        else echo "$progressbar";
    }while( $status["running"] );
    fclose($pipes[0]);
    fclose($pipes[2]);
    echo "'nProcess complete. 'n";
    print_r( $status );
}else{
   echo "Failed to run process.'n";
}

输出如下所示:

ran process
|>                    |  00%
|==>                  |  10%
|====>                |  20%
|======>              |  30%
|========>            |  40%
|==========>          |  50%
|============>        |  60%
|==============>      |  70%
|================>    |  80%
|==================>  |  90%
|====================>| 100%
Process complete.
Array
(
    [command] => /usr/bin/env ruby ./rlike.rb 1 10
    [pid] => 60306
    [running] =>
    [signaled] =>
    [stopped] =>
    [exitcode] => 0
    [termsig] => 0
    [stopsig] => 0
)

最后,编写进度条的ruby程序如下所示(注意,ruby语法的神奇之处:)):

wait = ARGV[1].to_f || 10.0
repeat = ARGV[2].to_i
repeat = 10 if !repeat or repeat == 0
wait = 1 if !wait or wait == 0
barlen = 20
(repeat+1).times do |t|
    curlen = ( repeat == 0 ? 0 : ( t*barlen/repeat ) )
    bar = ( "%#{curlen}s>" % "" ).gsub( " ", "=")
    $stderr.print sprintf("'r|%- #{barlen+1}s| %3.2d%% ", bar, 100*t/repeat )
    $stderr.flush
    sleep 1 unless t == repeat
end

从那个例子中,你应该能够得到任何你喜欢的工作。警告:我每次重写整个进度条并返回到'r行的开头-但取决于Rscript进度条的工作方式,情况可能并非如此。

您需要传递一个变量给exec以获得返回值。来自文档:

string exec ( string $command [, array &$output [, int &$return_var ]] )

return_var如果return_var参数与参数,则返回所执行命令的状态写入该变量

所以,你的代码可能看起来像这样:
exec(" RScript ~/dynamic.R 'select field1, field2 from table where 1=1 limit 100' ", $output, $return_var);

在上面,$return_var将返回命令的状态。