PHP - proc_get_status 'выполняется', возвращая false, когда исполняемый файл javaw все еще работает
Я выполняю javaw с java-файлом с бесконечным циклом, используя это:
$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
атрибут возвращает истину. На втором звонке (через секунду) proc_get_status
, running
возвращает ложь Приложение javaw.exe все еще работает, однако (я звоню proc_get_status
в то время как цикл, который в конечном итоге будет тайм-аут.)
Моя цель - убить программу по истечении времени ожидания. Смотрите аналогичный вопрос здесь. Я работаю на Win7 64 бит, PHP 5.3
Вар дамп на $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'] отличается от pid для javaw.exe в Windows' Resource Monitor.
3 ответа
Хотя мы не могли точно определить проблему с 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
немедленно, если нет данных, ожидающих).
Так как вы упомянули, что вы делаете это на окнах, я понял, что происходит-
javaw (с буквой W) запускает его как приложение для Windows и сразу же возвращает (поэтому работает =false)
вам нужно использовать Java (без W), чтобы запустить его в консоли.
java = console application
javaw = windows application with no console