0

我正在使用一个无限循环的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_statusrunning属性返回true。在第二次调用(一秒后)到 时proc_get_statusrunning返回false。但是,应用程序 javaw.exe仍在运行(我调用proc_get_status了一个最终会超时的 while 循环。)

我的目标是在超时后终止程序。在这里看到一个类似的问题。我在 Win7 64 位 PHP 5.3 上运行

Var dump on $status:(注意;我尝试申请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 不同。

4

3 回答 3

1

尽管我们无法确定 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;
        }


}
于 2012-08-30T23:06:51.657 回答
1

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

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

如果您不关心输出,请将其发送到/dev/null以摆脱它:

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

如果您选择从管道读取数据,如果没有数据,读取函数将阻塞 - 绕过您可能想要使用的问题:

stream_set_blocking($pipes[0], 0)

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

于 2012-08-28T18:56:04.497 回答
0

既然你提到你在 Windows 上这样做,我意识到发生了什么-

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

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

java = console application
javaw = windows application with no console
于 2012-08-30T22:47:10.037 回答