Используйте PHP proc_open + bypass_shell для запуска исполняемого файла в фоновом режиме и получения правильного PID? - PullRequest
5 голосов
/ 23 августа 2011

Итак, в PHP на Windows: возможно ли запустить исполняемый файл в фоновом режиме И получить его PID ? Я пришел к выводу, что обе задачи можно выполнять по отдельности, но не вместе.

Фоновая обработка процесса

Чтобы создать фоновый процесс, запускаемый через SHELL, необходимо использовать команду 'start /B "bg" myprog.exe', а процесс SHELL должен быть закрыт сразу после.

Для этого многие люди используют pclose( popen( ... ) ) примерно так pclose( popen( 'start /B "bg" myprog.exe', 'r') );, но, насколько мне известно, невозможно извлечь pid при использовании popen.

Поскольку невозможно получить pid с popen, мы должны обратиться к proc_open.

Получение PID

Используя proc_open, мы можем получить pid exe, если и только если bypass_shell имеет значение true.

Если для bypass_shell установлено значение false (по умолчанию), Windows возвращает pid ОБОЛОЧКИ. Для получения дополнительной информации см .: https://bugs.php.net/bug.php?id=41052

Объяснение проблемы

Команда start /B завершается неудачно при передаче в proc_open при bypass_shell = true, поскольку она пропускает SHELL и отправляет аргументы командной строки непосредственно в myprog.exe, который не знает, что с ними делать.

И наоборот, если bypass_shell = false (по умолчанию) и proc_close используются для немедленного закрытия ОБОЛОЧКИ, myprog.exe запускается в фоновом режиме, как при использовании pclose( popen( ... ) ) НО неверный pid вернулся (мы получаем pid из снаряда).

Итак, возможно ли фоновое отображение + правильный поиск pid возможно?

Если нет, то какая следующая лучшая вещь? Мне нужно сделать это для PHP-скрипта, который будет развернут на общем хостинге, чтобы сторонние расширения не могли быть установлены. Лучшее, что я могу придумать, это сделать снимок tasklist до и после запуска myprog.exe в фоновом режиме, а затем провести перекрестный анализ результатов. Обратите внимание, что myprog.exe может работать одновременно.

Если это помогает, хотя это не должно иметь никакого значения, myprog.exe на самом деле является ffmpeg (который устанавливается на большинстве общих веб-хостов).

Временное решение

// background the process
pclose( popen( 'start /B "bg" ffmpeg.exe', 'r') );

// get the pid using tasklist
exec( 'TASKLIST /NH /FO "CSV" /FI "imagename eq ffmpeg.exe" /FI "cputime eq 00:00:00"', $output );
$output = explode( '","', $output[0] );
$pid = $output[1];

1 Ответ

1 голос
/ 08 мая 2013

это не совсем ответ на вопрос OP, так как он не будет работать на Windows-сервере, но он будет отлично работать на любом Linux-сервере с включенной exec (), так что это может кому-то помочь;)

$pidfile = 'myPidFile'; //coule be done better with tempnam(), but for this example will do like that ;)
$outputfile = '/dev/null'; //can be any text file instead of /dev/null. output from executable will be saved there
$cmd = 'sleep 30'; // this would normaly take 30 seconds
exec(sprintf("%s > %s 2>&1 & echo $! > %s", $cmd, $outputfile, $pidfile));

$pid = file_get_contents($pidfile);
echo $pid;
//delete pid file if you want
//unlink($pidfile);
...