windows - Brug PHP's proc\_open + bypass\_shell til at køre en eksekverbar i baggrunden og hent den korrekte PID?

Indlæg af Hanne Mølgaard Plasc

Problem



Så, i PHP på Windows: er det muligt at både køre en eksekverbar i baggrunden OG hent sin PID ? Jeg har udledt, at det er muligt at udføre begge opgaver separat, men ikke sammen.


Baggrund for processen



Til baggrund skal en proces, der startes via SHELL, kommandoen 'start /B "bg" myprog.exe' bruges, og SHELL-processen skal lukkes umiddelbart efter.


For at gøre dette bruger mange mennesker pclose( popen( ... ) ) som sådan pclose( popen( 'start /B "bg" myprog.exe', 'r') ); men efter min viden er det umuligt at hente pid, når du bruger popen.


Fordi det er umuligt at få pid med popen, må vi se til proc\_open.


Får PID



Ved hjælp af proc\_open kan vi hente exe pid, hvis og kun hvis bypass\_shell er sat til sand.


Hvis bypass\_shell er sat til falsk (standard), returnerer Windows pid af SHELL. For mere info se: https://bugs.php.net/bug.php?id=41052[19]


Problemet forklaret



Kommandoen start /B mislykkes, når den sendes til proc\_open når bypass\_shell = true, fordi den hopper over SHELL og sender kommandolinjerne direkte til myprog.exe, som ikke ved hvad de skal gøre med dem.


Omvendt, hvis bypass\_shell = false (standard) og proc\_close bruges til at lukke SHELL med det samme, kører myprog.exe i baggrunden ligesom ved brug af pclose( popen( ... ) ) MEN forkert pid returneres (vi får SHELLs pid.


Så er backgrounding + korrekt pid hentning muligt?


Hvis ikke, hvad er det næste bedste? Jeg skal gøre dette til et PHP script, der vil blive implementeret på delt hosting, så ingen tredjepartsudvidelser kan installeres. Det bedste jeg kan komme med er at tage et øjebliksbillede af [[tasklist før og efter lanceringen af ​​myprog.exe i baggrunden og derefter krydsanalyse af resultaterne. Bemærk at myprog.exe kan køre samtidigt.


Hvis det hjælper, selvom det ikke skal gøre en forskel, er myprog.exe faktisk ffmpeg (som installeres på de fleste delte webhosts).


En midlertidig løsning



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

Bedste reference


Dette er ikke ligefrem et svar på OPs spørgsmål, da det ikke virker på Windows server, men det fungerer fint på enhver linux-server med exec () aktiveret, så det kan hjælpe nogen;)


$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);