문제

I have a PHP script (worker in gearman) that calls Rscript (with status progress bar) which runs fine but I don't know the status of the program. My question if it is possible for rscript to return run status back to php script.

<?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' ");
?>

So dynamic.R performs som data manipulations for 100 rows (i have plyr fucntion with progress bar) but with gearman progress bar does not show hence would like to show progress in gearman.

Hope my question makes sense

Regards, Savi

도움이 되었습니까?

해결책

you could theoretically do this with exec() if you redirected output and then read the output from a file, but coordinating with the process would be nearly impossible without first finding its PID. This is what proc_open() is for. popen() might work, but I'm guessing the progress bar is written to stderr, and that is what I mocked up for you here.

Here's a little program that should be a working example for you:

<?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";
}

The output looks like this:

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
)

Finally, the ruby program that writes out a progress bar looks as follows ( behold, the awesomeness of ruby syntax :) ):

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

From that example, you should be able to get anything you like working. Word of warning: I'm rewriting the entire progress bar each time and returning to the beginning of the line with \r - but depending on how the Rscript progress bar works, this may not be the case.

다른 팁

You need to pass a variable to exec in order to get the return value. From the documentation:

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

return_var If the return_var argument is present along with the output argument, then the return status of the executed command will be written to this variable.

So, your code might look something like this:

exec(" RScript ~/dynamic.R 'select field1, field2 from table where 1=1 limit 100' ", $output, $return_var);

In the above, $return_var will have the return status of your command.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top