proc_open
En esta página
proc_open
Ejecuta un comando y abre los punteros de ficheros para las entradas / salidas
Descripción#
proc_open(array $command, array $descriptor_spec, array $pipes, [string $cwd], [array $env_vars], [array $options]): resource
```php
`proc_open` es similar a `popen` pero proporciona un mayor grado de control sobre la ejecución del programa.
## Parámetros
`command`
El comando a ejecutar como `string`. Los caracteres especiales deben ser escapados correctamente, y una aplicación correcta de las comillas debe ser aplicada.
> [!NOTE]
> En *Windows*, a menos que `bypass_shell` esté definida a `true` en `options`, `command` es pasado a `cmd.exe` (en realidad, `%ComSpec%`) con el flag `/c` como un `string` *sin comillas* (es decir, exactamente como fue proporcionado a `proc_open`). Esto puede causar `cmd.exe` para eliminar las comillas que rodean `command` (para más detalles ver la documentación de `cmd.exe`), resultando en un comportamiento inesperado, y potencialmente peligroso, ya que los mensajes de error de `cmd.exe` pueden contener (una parte de) la `command` pasada (ver ejemplo a continuación).
A partir de PHP 7.4.0, `command` puede ser pasado como un `array` de argumentos de comandos. En este caso el proceso será abierto directamente (sin pasar por un shell) y PHP se encargará de escapar los argumentos necesarios.
> [!NOTE]
> En Windows, el escape de los argumentos de los elementos del `array` asume que el procesamiento de la línea de comandos del comando ejecutado es compatible con el procesamiento de argumentos de línea de comandos realizado por el runtime VC.
`descriptor_spec`
Un array indexado, donde las claves representan el número de descriptor y el valor el método con el cual PHP pasará este descriptor al proceso hijo. 0 es stdin, 1 es stdout, y 2 es stderr.
Cada elemento puede ser: Un array que describe el pipe a pasar al proceso. El primer elemento es el tipo del descriptor y los elementos siguientes son opciones para el tipo dado. Los tipos válidos son `pipe` (el segundo elemento es `r` para pasar el extremo de lectura del pipe al proceso, o `w` para pasar el extremo de escritura) y `file` (el segundo elemento es el nombre de fichero, y el tercer elemento es el modo de apertura del fichero, igual que `fopen`). Se debe notar que cualquier otro elemento diferente de `w` es tratado como `r`., Un recurso de flujo que representa un descriptor de fichero (por ejemplo, un fichero abierto, un socket, o bien `STDIN`).
Los números de punteros de ficheros no están limitados a 0, 1 y 2 - se puede especificar cualquier número de descriptor válido, y será pasado al proceso hijo. Esto permitirá que su script interactúe con otros scripts, y que sea ejecutado como "co-proceso". En particular, es muy práctico para pasar contraseñas a programas como PGP, GPG y openssl, con un método muy protegido. También es práctico para leer información de estado proporcionada por estos programas, en descriptores auxiliares.
`pipes`
Debe ser definido como un array indexado de punteros de ficheros que corresponden al extremo de cualquier descriptor PHP que sean creados.
`cwd`
El directorio inicial de trabajo del comando. Esto debe ser una ruta **absoluta** al directorio o `null` si se quiere utilizar el valor por omisión (el directorio de trabajo del proceso PHP actual)
`env_vars`
Un array que contiene las variables de entorno para el comando que debe ser ejecutado, o `null` para utilizar el mismo entorno que el proceso PHP actual
`options`
Permite especificar opciones adicionales. Las opciones actualmente soportadas son: `suppress_errors` (solo Windows): supresión de errores generados por esta función cuando está definida a `true`, `bypass_shell` (solo Windows): omisión del shell `cmd.exe` cuando está definida a `true`, `blocking_pipes` (solo Windows): fuerza los pipes bloqueantes cuando está definida a `true`, `create_process_group` (solo Windows): permite al proceso hijo manejar los eventos `CTRL` cuando está a `true`, `create_new_console` (solo Windows): el nuevo proceso tiene una nueva consola, en lugar de heredar la consola de su padre.
## Valores devueltos
Retorna un recurso que representa el proceso, que podrá ser utilizado por la función `proc_close` cuando ya no sea necesario. En caso de fallo, `false` será retornado.
## Errores/Excepciones
A partir de PHP 8.3.0, se lanza una excepción ValueError si `command` es un array sin al menos un elemento no vacío.
## Historial de cambios
| Versión | Descripción |
|----|----|
| 8.3.0 | Se lanzará una excepción ValueError si `command` es un array sin al menos un elemento no vacío. |
| 7.4.4 | Se añadió la opción `create_new_console` al parámetro `options`. |
| 7.4.0 | `proc_open` ahora acepta un `array` para `command`. |
| 7.4.0 | Se añadió la opción `create_process_group` al parámetro `options`. |
## Ejemplos
Ejemplo con `proc_open`
'); fclose($pipes[0]);
echo stream_get_contents($pipes[1]);
fclose($pipes[1]);
// Es importante que cierre los pipes antes de llamar
// a proc_close para evitar un bloqueo.
$return_value = proc_close($process);
echo "El comando retornó $return_value\n";
} ?>
Resultado del ejemplo anterior es similar a:
Array
(
[some_option] => aeiou
[PWD] => /tmp
[SHLVL] => 1
[_] => /usr/local/bin/php
)
El comando retornó 0
Comportamiento extraño de `proc_open` en Windows
Aunque se podría esperar que el siguiente programa busque el fichero `filename.txt` para el texto `search` y muestre los resultados, se comporta de manera diferente.
El ejemplo anterior mostrará:
'findstr" "search" "filename.txt' no se reconoce como un comando interno o externo,
programa ejecutable o archivo por lotes.
Para evitar este comportamiento, generalmente es suficiente rodear `command` con comillas adicionales:
$cmd = '""findstr" "search" "filename.txt""';
```php
Notas#
[!NOTE] Compatibilidad Windows: los descriptores más allá de 2 (stderr) son accesibles al proceso hijo, en forma de punteros heredados, pero como la arquitectura Windows no asocia números a los descriptores de bajo nivel, el proceso hijo no tiene, actualmente, ningún medio para acceder a ellos. Por otro lado, stdin, stdout y stderr funcionan como de costumbre.
[!NOTE] Si solo se necesita un proceso unidireccional,
popenserá más práctico, ya que es más sencillo de utilizar.
Véase también#
popen, exec, system, passthru, stream_select, Las comillas invertidas