pclose()
PHP incluye pclose(), función que cierra un puntero de proceso abierto por popen() y devuelve el código de salida del proceso.
La función PHP pclose()
La función PHP pclose() cierra un puntero de archivo de proceso — el flujo especial devuelto por popen() al ejecutar un comando externo. Mientras que fclose() simplemente cierra un descriptor de archivo normal, pclose() hace algo adicional: espera a que el proceso subyacente termine y te devuelve su estado de salida.
Esta página cubre la sintaxis, el valor de retorno (y un detalle importante al respecto), un ejemplo completo de lectura y cierre, y cuándo deberías usar proc_open() en su lugar.
Por qué existe pclose()
popen() ejecuta un comando de shell y te proporciona una tubería para enviarle datos de entrada (modo 'w') o leer su salida (modo 'r'). Esa tubería está respaldada por un proceso real del sistema operativo. Si simplemente abandonas el descriptor — o lo cierras con la función incorrecta — el proceso puede quedar como un zombie y su código de salida se pierde. pclose() es la contraparte correcta: vacía la tubería, bloquea hasta que el proceso hijo termine, lo recolecta y devuelve el código de salida para que tu script pueda reaccionar ante el éxito o el fracaso.
Siempre empareja cada
popen()con unpclose(). Usarfclose()en un descriptor depopen()es comportamiento indefinido.
Sintaxis
pclose(resource $handle): intParámetros
La función acepta un único parámetro:
$handle— el puntero de archivo de proceso devuelto porpopen(). No es válido pasar ningún otro tipo de recurso.
Valor de retorno
pclose() devuelve el estado de terminación del proceso como un entero (este es el valor bruto de la llamada C pclose — en la mayoría de los sistemas, el código de salida real está en el byte alto). Devuelve -1 si el proceso no pudo ser recolectado. En versiones antiguas de PHP, pasar un descriptor inválido emite una advertencia y devuelve FALSE.
Para obtener el código de salida simple en un sistema tipo Unix, desplaza el valor 8 bits a la derecha:
$status = pclose($handle);
$exitCode = $status >> 8; // 0 means the command succeededEjemplo
Abre un comando, lee su salida, luego cierra la tubería e inspecciona el resultado:
<?php
// Run an external command and read its output.
$handle = popen('ls -la', 'r');
if ($handle === false) {
die("Failed to start the command.\n");
}
$output = '';
while (!feof($handle)) {
$output .= fread($handle, 1024);
}
echo $output;
// Close the pipe and capture the process exit status.
$status = pclose($handle);
$exitCode = $status >> 8;
echo "Command exited with code: $exitCode\n";Abrimos un puntero de archivo de proceso con popen(), leemos la salida completa en un bucle con fread() (un único fread puede no capturar todo en salidas grandes), luego cerramos la tubería con pclose() y decodificamos el código de salida. Un código de salida de 0 significa convencionalmente éxito.
Errores comunes
- No mezcles
fclose()ypclose(). Un descriptor depopen()debe cerrarse conpclose(), y un descriptor defopen()confclose(). pclose()bloquea. Espera a que el proceso hijo termine. Si el comando nunca termina, tu script se quedará bloqueado.- Lee antes de cerrar.
pclose()puede descartar cualquier salida en búfer no leída, así que termina de leer la tubería primero. - Una dirección por tubería. Una tubería
popen()es legible o escribible, pero no ambas — para comunicación bidireccional necesitasproc_open().
Cuándo usar proc_open() en su lugar
popen()/pclose() son perfectos para un comando rápido de un solo uso en el que solo necesitas su salida o necesitas enviarle datos de entrada. Cuando necesitas ambas cosas al mismo tiempo, separar stdout y stderr, controlar el entorno o establecer un directorio de trabajo, usa proc_open() — te da control bidireccional completo sobre el proceso iniciado.
Conclusión
pclose() es el complemento obligatorio de popen(): cierra la tubería del proceso, espera a que el comando termine y devuelve su estado de salida para que puedas verificar que el comando tuvo éxito. Siempre empareja los dos, lee la tubería antes de cerrarla y recuerda desplazar el estado 8 bits a la derecha para leer el código de salida real en sistemas Unix. Para cualquier cosa que vaya más allá de una tubería de una sola dirección, usa proc_open().