7

那么,在 Windows 上的 PHP 中:是否可以在后台运行可执行文件并检索其 PID?我推断可以分别完成这两项任务,但不能一起完成。

后台处理过程

要使通过 SHELL 启动的进程后台运行,'start /B "bg" myprog.exe'必须使用该命令并且之后必须立即关闭 SHELL 进程。

为此,很多人都这样使用pclose( popen( ... ) ),但据我所知,使用 popen 时pclose( popen( 'start /B "bg" myprog.exe', 'r') );无法检索到。pid

因为用 popen 是不可能得到的pid,所以我们必须查看 proc_open。

获取 PID

当且仅当设置为 true时,我们可以检索exeproc_open的 pid 。 bypass_shell

如果bypass_shell设置为 false(默认值),Windows 将返回pidSHELL。欲了解更多信息,请参阅:https ://bugs.php.net/bug.php?id=41052

问题解释

start /B命令在传递给 proc_open 时失败,bypass_shell = true因为它跳过了 SHELL 并将命令行参数直接发送到不知道如何处理它们的 myprog.exe。

相反,如果bypass_shell = false(默认)和 proc_close 用于立即关闭 SHELL,myprog.exe 就像使用时一样在后台运行,pclose( popen( ... ) )但返回不正确 pid(我们得到pid了 SHELL)。

那么,后台+正确的pid检索可能吗?

如果不是,那么下一个最好的事情是什么?我需要为将部署在共享主机上的 PHP 脚本执行此操作,因此无法安装第三方扩展。我能想到的最好的tasklist办法是在后台启动 myprog.exe 之前和之后拍摄快照,然后交叉分析结果。请注意,myprog.exe 可以同时运行。

如果它有帮助,虽然它不应该有所作为,myprog.exe 实际上是 ffmpeg(它安装在大多数共享的 webhosts 上)。

临时解决方案

// 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];
4

1 回答 1

-1

这不完全是 OP 问题的答案,因为它不能在 Windows 服务器上工作,但它可以在任何启用 exec() 的 Linux 服务器上正常工作,所以它可能对某人有帮助;)

$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);
于 2013-05-08T19:30:22.273 回答