PHP-proc_get_status';正在运行';当javaw可执行文件仍在运行时返回false


PHP - proc_get_status 'running' returning false when javaw executable still running

我正在用一个无限循环的java文件执行javaw,使用这个:

$descriptorspec = array(
                                0 => array("pipe", "r"),  // stdin is a pipe that the child will read from
                                1 => array("pipe", "w"),  // stdout is a pipe that the child will write to
                                2 => array("pipe", "w") // stderr is a file to write to
                        );
 // e.x. $javaCmd = "java -cp "../Fully Diversified Sequences of Sets" SuperEasyProblemSolution2 > /dev/null 2>&1 < h.in"
$proc = proc_open($javaCmd, $descriptorspec, $pipes);//, $cwd, $env);
 stream_set_blocking($pipes[0], 0) ;
 $status = proc_get_status($proc);  
 var_dump($status);
  $timeOut = 5;
  $currentSecond = 0;
  while( $currentSecond < $timeOut ) {
        echo '<br/>';
        sleep(1);
        $currentSecond = $currentSecond +1;
        if( ! $status["running"] )
        {
            echo 'process exited before timing out'; // Process must have exited, success!
            return;
        }
        $status = proc_get_status($proc);
        var_dump($status);
  } // end while
  if($currentSecond  == $timeOut)
  {
      // kill KILL KILL!
      exec("taskkill /PID ".$status['pid']);
  }

在第一次调用proc_get_status时,running属性返回true。在对proc_get_status的第二次调用(一秒钟后),running返回false。应用程序javaw.exe仍在运行,但是(我在while循环中调用proc_get_status,该循环最终将超时。)

我的目标是在超时后终止程序。请参阅此处的类似问题。我在Win7 64位,PHP 5.3 上运行

$status上的Var转储:(注意;我尝试应用stream_set_blocking($pipes[0], 0) ;,相同的问题)

进入超时循环前:

    array(8) { 
["command"]=> string(157) "java -cp "../Fully Diversified Sequences of Sets" SuperEasyProblemSolution2 /dev/null 2>&1 < h.in" 
["pid"]=> int(3264) 
["running"]=> bool(true) 
["signaled"]=> bool(false) 
["stopped"]=> bool(false) 
["exitcode"]=> int(-1) 
["termsig"]=> int(0) 
["stopsig"]=> int(0) 
} 

第一次迭代/睡眠后(1):

    array(8) { 
["command"]=> string(157) "java -cp "../Fully Diversified Sequences of Sets" SuperEasyProblemSolution2 /dev/null 2>&1 < h.in" 
["pid"]=> int(3264) 
["running"]=> bool(false) 
["signaled"]=> bool(false) 
["stopped"]=> bool(false) 
["exitcode"]=> int(1) 
["termsig"]=> int(0) 
["stopsig"]=> int(0) 
} 
    process exited before timing out

测试后,$status['pid']似乎与Windows"资源监视器"下javaw.exe的pid不同。

尽管我们无法确定proc_get_status返回错误布尔值的问题,但我们能够找到一个很好的解决方案(针对Unix),使用

if (file_exists("/proc/".$status["pid"])) { // process still running }

以检查进程是否仍在运行。

以下是完整的代码摘录:

$proc = proc_open($javaCmd, array(array("pipe", "r"), array("pipe", "w"), array("pipe", "w")), $pipes);
$status = proc_get_status($proc);
if($status["pid"] === false)
{
    // Process did not execute correctly
}
else
{
        $timeOut = 0;
        $forceKill = true;
        while($timeOut < $timeLimit)
        {
            $timeOut++;
            sleep(1);
            echo 'Timeout is at '.$timeOut.' and timelimit: '.$timeLimit.'<br/>';
            if (file_exists("/proc/".$status["pid"])) {
            // process still running
            }
            else
            {
                echo 'Finished running after '.$timeOut.' seconds<br/>';
                $forceKill = false;
                break;
            }
        }
        if($forceKill == true)
        {
            echo ' Manual killing pid '.$status['pid'];
            exec("sudo kill ".$status['pid']);
            $runTime = $timeLimit;
        }

}

如果Java应用程序作为守护进程运行,那么它将具有不同的PID。

Java应用程序是否尝试输出任何内容?如果是这样,那么您没有读取管道,因此脚本最终会填满缓冲区并挂起(这可能会导致Java停止运行)

如果您不关心输出,则将其发送到/dev/null以消除它:

/cmd/to/run > /dev/null 2>&1

如果您选择从管道中读取数据,如果没有数据,读取功能将被阻止-绕过您可能想要使用的数据:

stream_set_blocking($pipes[0], 0)

这将关闭阻塞模式(如果没有数据等待,读取功能将立即返回FALSE)。

自从你提到你在windows上这样做后,我意识到发生了什么-

javaw(带W)将其作为windows应用程序启动并立即返回(这就是为什么running=false)

您需要使用java(不带w)在控制台中运行它。

java = console application
javaw = windows application with no console