¿Cómo esperar un proceso ejecutado por proc_open () en php?

por favor, después de leer esta pregunta, no diga que está copiada. Ya he buscado en la web pero ninguna de las soluciones funcionó para mí.

Qué estoy haciendo: ->
Estoy tomando un archivo fuente (digamos .c) a través de php ejecutando el servidor apache en el host local.Estoy guardando ese archivo en el directorio “/ code /” y comstackndo y ejecutando este archivo fuente usando proc_open () en php.Ahora quiero esperar la secuencia de comandos php principal hasta que termine el proceso creado por “proc_open ()”, entonces utilicé “pcntl_waitpid ()”. Pero creo que hay un problema al usar “pcntl_waitpid ()” porque la secuencia de comandos después de “pcntl_waitpid ()” no se está ejecutando. El proceso creado por “pcntl_waitpid ()” toma la entrada del archivo “/code/input.txt” y da salida al archivo “/code/output.txt”, por lo que para el propósito de la redirección estoy usando proc_open (), para que pueda fácilmente redirigir las transmisiones

La configuración de mi máquina: –
SO -> Ubuntu 12.04 LTs
PHP 5.3.10
APACHE 2.2.22
Ejecutando en el host local

Permisos: –
/ código -> 777
Carpeta donde reside el archivo php principal -> 777 (Sé que 777 no es bueno por razones de seguridad, pero como estoy ejecutando script en el servidor local, no tengo problemas con estos permisos).

Lo que quiero: – ¿Alguien puede decirme de alguna manera para que pueda detener el script php principal hasta que el proceso creado por proc-open () finalice o si alguien me puede decir otra forma de cumplir con mi requisito de redirección?

Aquí hay una parte del código:

$descriptors = array( 2 => array("pipe","w") ); $process = proc_open($cmd,$descriptors,$pipes,$code); sleep(2); if(is_resource($process)) { $status = proc_get_status($process); $pid = $status ["pid"]; echo getmypid()."
"; echo $pid; if(pcntl_waitpid($pid,$child_status) == -1) { fclose($pipes[2]); proc_close($process); exit("Sorry!Unable to compile the source_file.\n"); } while(!file_exists("/code/test")) { proc_close($process); echo stream_get_contents($pipes[2]),"\n"; fclose($pipes[2]); exit("Sorry!Unable to compile the source_file.\n"); } echo "Compiled Successfully!\n"; echo "Running test cases...\n"; fclose($pipes[2]); proc_close($process); } else { exit("Sorry!Unable to compile the source_file.\n"); }

¡GRACIAS!

Lo mejor es usar tuberías para este problema. pcntl_wait () es solo Linux, y no es muy útil (en mi experiencia) a menos que trabajes con fork (). Use stream_select para esperar. Si es necesario, profundizaré en mis antiguos scripts, pero es algo así como:

 < ?php $cwd = "/code/"; chmod("/code/test.c",0777); switch($xtension) { case "c": $cmd = "gcc -g test.c -o test -lm "; break; case "cpp": $cmd = "g++ -g test.cpp -o test"; break; case "java": $cmd = "javac test.java"; break; } $descriptors = array( 0 => array('pipe', 'r'), // stdin 1 => array('pipe', 'w'), // stdout 2 => array('pipe', 'a') // stderr ); $process = proc_open($cmd,$descriptors,$pipes,$code); stream_set_blocking($pipes[2], 0); if(($error = stream_get_contents($pipes[2]) !== false) { // error starting command (error *in* command) die($error); }else { stream_set_blocking($pipes[2], 1); /* Prepare the read array */ $read = array($pipes[1], $pipes[2]); $write = NULL; $except = NULL; $tv_sec = 0; // secs $tv_usec = 1000; // millionths of secs if(false === ($rv = stream_select($read, $write, $except, $tv_sec, $tv_usec))) { die('error in stream_select'); }else if ($rv > 0) { foreach($read as $pipe_resource) { if($pipe_resource == $pipes[1]) { // is stdout }else if($pipe_resource == $pipes[2]) { // is stderr } } }else { // select timed out. plenty of stuff can be done here } } // this will be executed after the process terminates 

Hay muchas maneras en que puede usar esto para resolver su problema.

Primero, puede configurar el tiempo de espera en Select a cero y esperará indefinidamente. Si su ejecutable no usa stdout, la función stream_select se bloqueará hasta que las tuberías se cierren cuando finalice el proceso.

Si su proceso utiliza stdout y stderr, puede usar la selección en un bucle y verificar si las tuberías están cerradas cada vez que se selecciona select. Esto también le permitirá procesar de manera útil la información de stdout y stderr si es necesario en el futuro (json es increíble para esto).

Aquí está mi ir en ello (leyendo tanto stdout y stderr (con suerte) sin interlockings):

 class ExecResult { public $returnValue; public $stdoutBuffer; public $stderrBuffer; } class WtfPhpWhyIHaveToDoEverythingMyself { public static function exec($proc, $argv) { $cwd = getcwd(); $env = []; $procAndArgv = count($argv) > 0 ? $proc . ' ' . implode(' ', self::escapeArgvs($argv)) : $proc; $pipes = null; // will get filled by proc_open() $result = new ExecResult(); $processHandle = proc_open( $procAndArgv, [ 0 => ['pipe', 'r'], // read/write is from child process's perspective 1 => ['pipe', 'w'], 2 => ['pipe', 'w'] ], $pipes, $cwd, $env); $stdin = $pipes[0]; $stdout = $pipes[1]; $stderr = $pipes[2]; fclose($stdin); stream_set_blocking($stdout, false); stream_set_blocking($stderr, false); $outEof = false; $errEof = false; do { $read = [ $stdout, $stderr ]; // [1] $write = null; // [1] $except = null; // [1] // [1] need to be as variables because only vars can be passed by reference stream_select( $read, $write, $except, 1, // seconds 0); // microseconds $outEof = $outEof || feof($stdout); $errEof = $errEof || feof($stderr); if (!$outEof) { $result->stdoutBuffer .= fgets($stdout); } if (!$errEof) { $result->stderrBuffer .= fgets($stderr); } } while(!$outEof || !$errEof); fclose($stdout); fclose($stderr); $result->returnValue = proc_close($processHandle); return $result; } private static function escapeArgvs($argv) { return array_map(function ($item){ return escapeshellarg($item); }, $argv); } } $result = WtfPhpWhyIHaveToDoEverythingMyself::exec('/var/www/html/hello.sh', [ 'arg 1', 'arg 2', ]); var_dump($result); /* object(ExecResult)#1 (3) { ["returnValue"]=> int(0) ["stdoutBuffer"]=> string(45) "var1 = arg 1 var2 = arg 2 " ["stderrBuffer"]=> string(0) "" } */ 

Estoy realmente decepcionado de que con PHP, usted tenga que escribir todas las tuberías usted mismo. Por ejemplo, node.js tiene la espalda cubierta con simple child_process.spawn ()