pclose()
A função pclose() do PHP fecha um ponteiro de arquivo de processo aberto por popen() e retorna o status de saída do processo.
A Função PHP pclose()
A função PHP pclose() fecha um ponteiro de arquivo de processo — o fluxo especial retornado por popen() ao iniciar um comando externo. Enquanto fclose() simplesmente fecha um identificador de arquivo normal, pclose() faz algo a mais: aguarda o processo subjacente terminar e retorna seu status de saída.
Esta página aborda a sintaxe, o valor de retorno (e um detalhe importante sobre ele), um exemplo completo de leitura e fechamento, e quando você deve usar proc_open() no lugar.
Por que pclose() existe
popen() executa um comando shell e fornece um pipe para alimentar dados nele (modo 'w') ou ler sua saída (modo 'r'). Esse pipe é respaldado por um processo real do sistema operacional. Se você simplesmente abandonar o identificador — ou fechá-lo com a função errada — o processo pode ficar como um zumbi e seu código de saída será perdido. pclose() é a contraparte correta: limpa o pipe, bloqueia até que o processo filho termine, o encerra e retorna o código de saída para que seu script possa reagir a sucesso ou falha.
Sempre associe cada
popen()a umpclose(). Usarfclose()em um identificador depopen()é comportamento indefinido.
Sintaxe
pclose(resource $handle): intParâmetros
A função recebe um único parâmetro:
$handle— o ponteiro de arquivo de processo retornado porpopen(). É inválido passar qualquer outro tipo de recurso.
Valor de Retorno
pclose() retorna o status de término do processo como um inteiro (este é o valor bruto da chamada C pclose — na maioria dos sistemas, o código de saída real está no byte mais alto). Retorna -1 se o processo não puder ser encerrado. Em versões mais antigas do PHP, passar um identificador inválido emite um aviso e retorna FALSE.
Para obter o código de saída simples em um sistema Unix, desloque o valor 8 bits para a direita:
$status = pclose($handle);
$exitCode = $status >> 8; // 0 means the command succeededExemplo
Abra um comando, leia sua saída e, em seguida, feche o pipe e inspecione o 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 um ponteiro de arquivo de processo com popen(), lemos a saída completa em um loop com fread() (um único fread pode não capturar tudo para saídas maiores), em seguida fechamos o pipe com pclose() e decodificamos o código de saída. Um código de saída 0 convencionalmente significa sucesso.
Armadilhas comuns
- Não misture
fclose()epclose(). Um identificador depopen()deve ser fechado compclose(), e um identificador defopen()comfclose(). pclose()bloqueia. Ele aguarda o processo filho terminar. Se o comando nunca terminar, seu script ficará travado.- Leia antes de fechar.
pclose()pode descartar qualquer saída em buffer não lida, portanto termine de ler o pipe primeiro. - Uma direção por pipe. Um pipe de
popen()é legível ou gravável, não ambos — para comunicação bidirecional você precisa deproc_open().
Quando usar proc_open() no lugar
popen()/pclose() são perfeitos para um comando rápido de uso único em que você só precisa de sua saída ou precisa alimentar dados nele. Quando você precisar das duas coisas ao mesmo tempo, separar stdout e stderr, controlar o ambiente ou definir um diretório de trabalho, use proc_open() — ele oferece controle bidirecional completo sobre o processo iniciado.
Conclusão
pclose() é o complemento obrigatório de popen(): fecha o pipe do processo, aguarda o comando terminar e retorna seu status de saída para que você possa verificar se o comando foi bem-sucedido. Sempre associe os dois, leia o pipe antes de fechá-lo e lembre-se de deslocar o status 8 bits para a direita para ler o código de saída real em sistemas Unix. Para qualquer coisa além de um pipe de direção única, use proc_open().