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

PHP-proc_get_status';运行';javaw可执行文件仍在运行时返回false,php,proc-open,Php,Proc Open,我正在用一个无限循环的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 t

我正在用一个无限循环的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']);
  }
第一次迭代/休眠后(1):

数组(8){
[“command”]=>string(157)“java-cp”。/完全多样化的集合序列“SuperEasyProblemSolution2/dev/null 2>&1int(3264)
[“正在运行”]=>bool(false)
[“已发信号”]=>bool(假)
[“已停止”]=>bool(false)
[“exitcode”]=>int(1)
[“termsig”]=>int(0)
[“stopsig”]=>int(0)
} 
进程在超时之前退出

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

如果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

虽然我们无法确定proc_get_status返回不正确的布尔值的问题,但是我们能够找到一个很好的解决方法(对于Unix),使用

if(文件_存在(“/proc/”$status[“pid”])){
//进程仍在运行
}

检查进程是否仍在运行

以下是完整的代码摘录:

$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;
        }


}
$proc=proc_open($javaCmd,数组(数组(“管道”、“r”)、数组(“管道”、“w”)、数组(“管道”、“w”)、$pipes);
$status=proc\u get\u status($proc);
如果($status[“pid”]==false)
{
//进程未正确执行
}
其他的
{
$timeOut=0;
$forceKill=true;
而($timeOut<$timeLimit)
{
$timeOut++;
睡眠(1);
echo“Timeout位于“.$Timeout.”和timelimit:“.$timelimit.”
; 如果(文件_存在(“/proc/”$status[“pid”])){ //进程仍在运行 } 其他的 { echo“在“.$timeOut.”秒后完成运行
; $forceKill=false; 打破 } } 如果($forceKill==true) { 回显“手动清除pid”。$状态['pid']; exec(“sudo kill”。$status['pid']); $runTime=$timeLimit; } }
请打印出两个结果的
$status
我已经发布了$status var\u dump一件我在辅助本地设备上测试时注意到的事情,java可执行文件没有显示在任务管理器中,而是显示在资源管理器中。在那里,它的PID为7600,而proc_get_status报告的PID为1096。我不关心输出-我只想确保它在特定的时间限制内运行。我尝试使用
/dev/null
流设置阻塞($pipes[0],0)
,但都不起作用。我在windows上运行,它可能是作为守护进程运行的。如果你把你的代码放在一个.bat文件中,并从命令行调用它会怎么样?我使用linux,所以我猜测windows是如何处理它的——但也许它返回的是重定向管道(javaw-cp…命令是什么意思?我试过了-它正常执行,但完成了,javaw继续运行。。。它可能完成了对作为
proc_get_status
的替代方案,我在java和javaw中都遇到了这个问题(我第一次使用java,然后尝试了javaw,我又回到了java)。我在检查/proc/$pid时取得了一些成功,因此我可能会放弃windows解决方案而坚持使用unix。
java = console application
javaw = windows application with no console
$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;
        }


}