那么,在 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 将返回pid
SHELL。欲了解更多信息,请参阅: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];