[英]PHP script stuck on exec even after running command in backgroud on Windows
I want a php script from which I can execute a program, and terminate it if it doesn't complete execution in 2 seconds. 我想要一个可以执行程序的php脚本,如果它在2秒钟内未完成执行,则终止它。 I am using Windows.
我正在使用Windows。 I have tried the following code:
我尝试了以下代码:
exec("start /B program.exe");
sleep(2);
exec('taskkill /F /IM "program.exe"');
This doesn't seem to work as script is stuck on the first exec
statement as long as program.exe
is not finished execution. 只要未将
program.exe
执行完毕,脚本就停留在第一个exec
语句上,这似乎不起作用。 I can't figure out how to do fix this issue. 我不知道如何解决此问题。
Right, exec()
will block until execution completes. 是的,
exec()
将阻塞直到执行完成。 This question has great answers for how to do an exec()
with a timeout. 这个问题对于如何使用超时
exec()
有很好的答案。 I think this will probably work best for you. 我认为这可能最适合您。 I'll post the code here for completeness (but I can't take any credit!):
为了完整起见,我将代码发布在这里(但我不能功劳!):
/**
* Execute a command and return it's output. Either wait until the command exits or the timeout has expired.
*
* @param string $cmd Command to execute.
* @param number $timeout Timeout in seconds.
* @return string Output of the command.
* @throws \Exception
*/
function exec_timeout($cmd, $timeout) {
// File descriptors passed to the process.
$descriptors = array(
0 => array('pipe', 'r'), // stdin
1 => array('pipe', 'w'), // stdout
2 => array('pipe', 'w') // stderr
);
// Start the process.
$process = proc_open('exec ' . $cmd, $descriptors, $pipes);
if (!is_resource($process)) {
throw new \Exception('Could not execute process');
}
// Set the stdout stream to none-blocking.
stream_set_blocking($pipes[1], 0);
// Turn the timeout into microseconds.
$timeout = $timeout * 1000000;
// Output buffer.
$buffer = '';
// While we have time to wait.
while ($timeout > 0) {
$start = microtime(true);
// Wait until we have output or the timer expired.
$read = array($pipes[1]);
$other = array();
stream_select($read, $other, $other, 0, $timeout);
// Get the status of the process.
// Do this before we read from the stream,
// this way we can't lose the last bit of output if the process dies between these functions.
$status = proc_get_status($process);
// Read the contents from the buffer.
// This function will always return immediately as the stream is none-blocking.
$buffer .= stream_get_contents($pipes[1]);
if (!$status['running']) {
// Break from this loop if the process exited before the timeout.
break;
}
// Subtract the number of microseconds that we waited.
$timeout -= (microtime(true) - $start) * 1000000;
}
// Check if there were any errors.
$errors = stream_get_contents($pipes[2]);
if (!empty($errors)) {
throw new \Exception($errors);
}
// Kill the process in case the timeout expired and it's still running.
// If the process already exited this won't do anything.
proc_terminate($process, 9);
// Close all streams.
fclose($pipes[0]);
fclose($pipes[1]);
fclose($pipes[2]);
proc_close($process);
return $buffer;
}
Edit 编辑
The 'exec' part of the proc_open()
probably won't work on Windows, but it's probably unnecessary. proc_open()
的“ exec”部分可能无法在Windows上运行,但可能没有必要。
Are you doing this with php cli (command line) ? 您是否正在使用php cli(命令行)执行此操作? Open a command prompt as administrator .
以管理员身份打开命令提示符 。
To not being blocked by waiting for the program close the process of opening the program . 为了不被等待程序阻塞而关闭程序的打开过程 。
php myscript.php
php myscript.php
pclose(popen("start /B program.exe", "r"));
sleep(2);
exec('taskkill /F /IM program.exe');
exit(0);
Would also be fine to put the exec start into a separate script and fire this script using exec
将exec开始放入一个单独的脚本并使用
exec
触发该脚本也可以
The first comment of the exec()
manual page shows a very simple example. exec()
手册页的第一条注释显示了一个非常简单的示例。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.