使用PHP的proc_open + bypass_shell在后台运行可执行文件并检索正确的PID?

leo*_*eoj 6 php windows background pid proc-open

因此,在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我们可以检索exe的pid当且仅当if bypass_shell设置为true.

如果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( ... ) )BUT 时返回错误 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];
Run Code Online (Sandbox Code Playgroud)

pat*_*ryk -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);
Run Code Online (Sandbox Code Playgroud)