所以,在Windows上的PHP中:是否可以在后台运行可执行文件并且检索其PID ?我已经推断出可以单独完成这两项任务,但不能一起完成。
要对通过SHELL启动的进程进行后台处理,必须使用命令'start /B "bg" myprog.exe'
,并且必须在之后立即关闭SHELL进程。
要做到这一点,很多人都会pclose( popen( ... ) )
使用pclose( popen( 'start /B "bg" myprog.exe', 'r') );
,但据我所知,使用popen时无法检索pid
。
因为用popen获取pid
是不可能的,所以我们必须看看proc_open。
使用proc_open
我们可以检索exe的pid(如果,并且只有 bypass_shell
设置为true。
如果bypass_shell
设置为false(默认值),Windows将返回SHELL的pid
。有关详细信息,请参阅:https://bugs.php.net/bug.php?id=41052
start /B
命令在bypass_shell = true
传递给proc_open时失败,因为它跳过SHELL并将命令行参数直接发送到myprog.exe,而myprog.exe不知道如何处理它们。
相反,如果使用bypass_shell = false
(默认值)和proc_close立即关闭SHELL,myprog.exe在后台运行就像使用pclose( popen( ... ) )
但不正确 pid
(我们得到SHELL的pid
。
那么,背景+正确的pid检索可能吗?
如果没有,那么下一个最好的东西是什么?我需要为将部署在共享主机上的PHP脚本执行此操作,因此不能安装第三方扩展。我能想到的最好的方法是在后台启动myprog.exe之前和之后拍摄tasklist
的快照,然后交叉分析结果。请注意,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];
答案 0 :(得分: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);