2011-01-23 18 views
8

Tengo una función de utilidad utilizada para ejecutar un programa a través de CLI (cmd, bash, etc.). Devuelve una matriz de 3 elementos: STDOUT, STDERR y EXIT CODE.PHP proc_open abre varias veces

Hasta ahora, ha funcionado bien sin problemas. De hecho, el problema que tengo con eso realmente no obstaculiza su funcionalidad, pero me preocupa el rendimiento.

El problema es que en ciertos casos, PHP ejecuta el mismo comando varias veces (3 veces en mi caso), incluso si se suponía que solo lo hiciera una vez.

/** 
* Executes a program and waits for it to finish, taking pipes into account. 
* @param string $cmd Command line to execute, including any arguments. 
* @param string $input Data for standard input. 
* @param boolean $log Whether to log execution failures or not (defaults to true). 
* @return array Array of "stdout", "stderr" and "return". 
*/ 
public static function execute($cmd,$stdin=null,$log=true){ 
    //static $once=true; if(!$once)die; $once=false; 
    $proc=proc_open($cmd, array(
     0=>array('pipe','r'), 
     1=>array('pipe','w'), 
     2=>array('pipe','w') ), $pipes); 
    fwrite($pipes[0],$stdin);    fclose($pipes[0]); 
    $stdout=stream_get_contents($pipes[1]); fclose($pipes[1]); 
    $stderr=stream_get_contents($pipes[2]); fclose($pipes[2]); 
    $return=proc_close($proc); 
    if($return!=0 && $log) 
     xlog('Error: Program execution returned failure.',$stdout,$stderr,$return); 
    return array('stdout'=>$stdout, 'stderr'=>$stderr, 'return'=>$return); 
} 

Tenga en cuenta la línea comentada (línea 9). Eso fue para probar. Lo habilité para garantizar que el programa objetivo solo se ejecute una vez (estaba pensando que mi código podría estar llamando a la misma función de alguna manera). Pero incluso con esa línea habilitada, el programa aún se ejecutó varias veces.

Como está, tengo 2 lugares en mi código donde estoy ejecutando el mismo programa (en diferentes ocasiones). La línea de comando es la misma para ambos.

Sin embargo, en una ocasión, el programa se ejecuta una vez, mientras que en la ocasión, PHP ejecuta el programa 3 veces.

He estado monitorizando y viendo este comportamiento en Process Explorer. Estoy usando Windows 7 x64. El programa es de 32 bits, al igual que PHP.

Edit: El programa en cuestión está desarrollado a medida, y no abre nuevos procesos.

+4

utilizar otra herramienta proceso para verificar la observación. No mencionó qué programa es (podría dividirse en subprocesos por sí mismo). – mario

+0

@Christian: ¿Cómo podemos verificarlo? Como dijiste, no mencionaste qué programa es. Mario tiene toda la razón; deberías escucharlo –

+0

Lo siento, quise decir "lo revisé" (ahora he eliminado el comentario para evitar confusiones). Lo que (signifiqué) es que lo revisé con Process Monitor. Editar: Y lo escuché;) lol – Christian

Respuesta

1

Su código para probar que se ejecuta una sola vez parece defectuoso.

Si tiene 2 procesos php en ejecución, no compartirán una variable estática. Por lo tanto, es posible que tenga solicitudes simultáneas que causen que esto se ejecute más de una vez.

En segundo lugar, debe establecer $once en falso al final de la función, de lo contrario, el die nunca será alcanzado.

Intente agregar algunos registros para ver si la función está siendo llamada desde dos veces.

Crea algunas pruebas de unidad/estrés que solo ejecutan la aplicación externa. Si ve múltiples procesos, entonces hay algo con su aplicación que está mal, no el código php.

+0

Lo estoy ejecutando localmente, por lo tanto, puedo ver todas las sesiones y los procesos que se abren. El programa se ejecuta solo una vez cuando se invoca por sí mismo. Estoy seguro de que mi declaración original es correcta. – Christian

+0

@Christian: cuando agrega el registro a la función, ¿parece que se la llama varias veces o el proceso se inicia varias veces mediante php windows o la aplicación? –

+0

@ByronWhitlock - El proceso en sí mismo se carga varias veces. El código comentado garantiza que la función solo se llame una vez. – Christian

0

Es muy extraño. Y es muy difícil de entender sin el código completo.

Si está haciendo hincapié en que su servidor llame a la misma página varias veces, mi mejor opción es probablemente relacionada con el proceso de operación por turnos de la CPU. El PHP no tiene tiempo para establecer la variable estática a falso porque al mismo tiempo hay otra solicitud para este método. Otra posibilidad es que PHP no puede aislar correctamente el valor estático y la solicitud diferente a este método puede leer la posición de la memoria diferente hasta que el PHP sincronice los valores.

0

Sé que esta puede no ser la mejor opción, pero esto es lo que hice. Aunque esto fue en Linux, pero estoy seguro de que hay una forma de llevar esto a Windows.

Lo que hice, fue ejecutar pgrep y comprobar si ya existía un comando como este y si lo hizo simplemente salir. Como dijiste, estás ejecutando el mismo comando (con parámetros exactos), así que simplemente verifica si ya hay un comando ejecutándose y actuando respectivamente.

que utiliza este comando:

$pid = shell_exec('pgrep -cfx "/* My command */"'); 
if ($pid > 1) return -1;