¿Cómo pasar el contenido de una variable a través de un comando externo en php?

StackOverflow https://stackoverflow.com/questions/7331527

  •  27-10-2019
  •  | 
  •  

Pregunta

Tengo una variable que contiene una cadena larga. (específicamente contiene algunos kilobytes de código javascript)

Quiero pasar esta cadena a través de un comando externo, en este caso un compresor de javascript, y capturar la salida del comando externo (el javascript comprimido) en php, asignándolo a una variable.

Soy consciente de que hay clases para comprimir javascript en php, pero este es simplemente un ejemplo de un problema general.

originalmente usamos:

$newvar = passthru("echo $oldvar | compressor");

Esto funciona para cadenas pequeñas, pero no es seguro. (si oldvar contiene caracteres con un significado especial para el shell, entonces podría pasar cualquier cosa)

Escapar con escapeshellarg soluciona eso, pero la solución se rompe para cadenas más largas, debido a las limitaciones del sistema operativo en la longitud máxima de argumento permitida.

Intenté usar popen("command" "w") y escribir en el comando; esto funciona, pero la salida del comando desaparece silenciosamente en el vacío.

Conceptualmente, solo quiero hacer el equivalente a:

$newvar = external_command($oldvar);
¿Fue útil?

Solución

Con la función proc_open , puede obtener identificadores para ambos stdouty stdin del proceso y así escribir sus datos en él y leer el resultado.

Otros consejos

Usando la sugerencia de rumpels, pude diseñar la siguiente solución que parece funcionar bien.Publicarlo aquí para beneficio de cualquier otra persona interesada en la pregunta.

public static function extFilter($command, $content){
    $fds = array(
        0 => array("pipe", "r"),  // stdin is a pipe that the child will read from
        1 => array("pipe", "w"),  // stdout is a pipe that the child will write to
        2 => array("pipe", "w")   // stderr is a pipe that the child will write to
    );
    $process = proc_open($command, $fds, $pipes, NULL, NULL);
    if (is_resource($process)) {
        fwrite($pipes[0], $content);
        fclose($pipes[0]);
        $stdout =  stream_get_contents($pipes[1]);
        fclose($pipes[1]);
        $stderr = stream_get_contents($pipes[2]);
        fclose($pipes[2]);
        $return_value = proc_close($process);
        // Do whatever you want to do with $stderr and the commands exit-code.
    } else {
        // Do whatever you want to do if the command fails to start
    }
    return $stdout;
}

Puede haber problemas de interbloqueo: si los datos que envía son más grandes que los tamaños combinados de las tuberías, entonces el comando externo se bloqueará, esperando que alguien lea desde su stdout, mientras php está bloqueado, esperando a que stdinser leído para dejar espacio para más información.

Posiblemente PHP se encarga de este problema de alguna manera, pero vale la pena probarlo si planea enviar (o recibir) más datos de los que caben en las tuberías.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top