pclose()
PHP offre un set completo di funzioni per le operazioni sul file system. Una di queste è pclose(), usata per chiudere un puntatore a file di processo
La funzione PHP pclose()
La funzione PHP pclose() chiude un puntatore a file di processo — lo stream speciale restituito da popen() quando si avvia un comando esterno. Mentre fclose() si limita a chiudere un normale handle di file, pclose() fa qualcosa in più: attende che il processo sottostante termini e restituisce il suo stato di uscita.
Questa pagina illustra la sintassi, il valore restituito (e una sottile insidia al riguardo), un esempio completo di lettura e chiusura, e quando conviene usare proc_open() al suo posto.
Perché esiste pclose()
popen() esegue un comando di shell e fornisce una pipe per inviare input (modalità 'w') o leggerne l'output (modalità 'r'). Quella pipe è supportata da un vero processo del sistema operativo. Se si abbandona semplicemente l'handle — o lo si chiude con la funzione sbagliata — il processo può restare come un zombie e il suo codice di uscita va perso. pclose() è la controparte corretta: svuota la pipe, si blocca finché il processo figlio non termina, lo raccoglie e restituisce il codice di uscita affinché lo script possa reagire a successo o fallimento.
Abbina sempre ogni
popen()a unpclose(). Usarefclose()su un handle dipopen()è un comportamento indefinito.
Sintassi
pclose(resource $handle): intParametri
La funzione accetta un singolo parametro:
$handle— il puntatore a file di processo restituito dapopen(). Non è valido passare qualsiasi altro tipo di risorsa.
Valore restituito
pclose() restituisce lo stato di terminazione del processo come intero (questo è il valore grezzo proveniente dalla chiamata C pclose — sulla maggior parte dei sistemi il codice di uscita effettivo si trova nel byte alto). Restituisce -1 se il processo non può essere raccolto. Nelle versioni più vecchie di PHP, passare un handle non valido emette un avviso e restituisce FALSE.
Per ottenere il codice di uscita semplice su un sistema Unix-like, si sposta il valore verso destra di 8 bit:
$status = pclose($handle);
$exitCode = $status >> 8; // 0 means the command succeededEsempio
Apri un comando, leggi il suo output, quindi chiudi la pipe e controlla il risultato:
<?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";Apriamo un puntatore a file di processo con popen(), leggiamo l'output completo in un ciclo con fread() (una singola fread potrebbe non catturare tutto per output di grandi dimensioni), quindi chiudiamo la pipe con pclose() e decodifichiamo il codice di uscita. Un codice di uscita pari a 0 significa convenzionalmente successo.
Errori comuni
- Non mescolare
fclose()epclose(). Un handle dapopen()deve essere chiuso conpclose(), e un handle dafopen()confclose(). pclose()si blocca. Attende che il processo figlio termini. Se il comando non termina mai, lo script si blocca lì.- Leggi prima di chiudere.
pclose()può scartare qualsiasi output bufferizzato non ancora letto, quindi termina prima la lettura della pipe. - Una direzione per pipe. Una pipe di
popen()è leggibile o scrivibile, non entrambe — per la comunicazione bidirezionale occorreproc_open().
Quando usare proc_open() al suo posto
popen()/pclose() sono perfetti per un comando rapido una tantum in cui si ha bisogno solo del suo output oppure occorre fornirgli input. Quando servono entrambe le cose contemporaneamente, separare stdout e stderr, controllare l'ambiente, o impostare una directory di lavoro, usa proc_open() — offre il controllo bidirezionale completo sul processo avviato.
Conclusione
pclose() è il compagno obbligatorio di popen(): chiude la pipe del processo, attende che il comando termini e restituisce il suo stato di uscita affinché tu possa verificare che il comando sia riuscito. Abbina sempre i due, leggi la pipe prima di chiuderla, e ricorda di spostare lo stato verso destra di 8 bit per leggere il codice di uscita reale sui sistemi Unix. Per qualsiasi cosa al di là di una pipe monodirezione, usa proc_open().