pclose()
PHP propose pclose() pour fermer un pointeur de fichier de processus ouvert par popen() et récupérer le code de sortie du processus.
La fonction PHP pclose()
La fonction PHP pclose() ferme un pointeur de fichier de processus — le flux spécial renvoyé par popen() lorsque vous lancez une commande externe. Là où fclose() se contente de fermer un descripteur de fichier ordinaire, pclose() fait quelque chose de plus : elle attend que le processus sous-jacent se termine et vous renvoie son code de sortie.
Cette page couvre la syntaxe, la valeur de retour (ainsi qu'un piège subtil à ce sujet), un exemple complet de lecture puis fermeture, et quand vous devriez préférer proc_open().
Pourquoi pclose() existe
popen() exécute une commande shell et vous donne un canal pour y envoyer des données (mode 'w') ou en lire la sortie (mode 'r'). Ce canal est adossé à un vrai processus du système d'exploitation. Si vous abandonnez simplement le descripteur — ou le fermez avec la mauvaise fonction — le processus peut rester en état de zombie et son code de sortie est perdu. pclose() est le pendant approprié : elle vide le canal, attend que le processus enfant se termine, le récupère et renvoie le code de sortie pour que votre script puisse réagir à la réussite ou à l'échec.
Associez toujours chaque
popen()à unpclose(). Utiliserfclose()sur un descripteur issu depopen()est un comportement indéfini.
Syntaxe
pclose(resource $handle): intParamètres
La fonction prend un seul paramètre :
$handle— le pointeur de fichier de processus renvoyé parpopen(). Passer tout autre type de ressource est invalide.
Valeur de retour
pclose() renvoie le statut de terminaison du processus sous forme d'entier (il s'agit de la valeur brute issue de l'appel C pclose — sur la plupart des systèmes, le code de sortie réel se trouve dans l'octet de poids fort). Elle renvoie -1 si le processus n'a pas pu être récupéré. Sur les anciennes versions de PHP, passer un descripteur invalide émet un avertissement et renvoie FALSE.
Pour obtenir le code de sortie brut sur un système de type Unix, décalez la valeur de 8 bits vers la droite :
$status = pclose($handle);
$exitCode = $status >> 8; // 0 means the command succeededExemple
Ouvrez une commande, lisez sa sortie, puis fermez le canal et examinez le résultat :
<?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";Nous ouvrons un pointeur de fichier de processus avec popen(), lisons la sortie complète dans une boucle avec fread() (un seul fread peut ne pas tout capturer pour des sorties volumineuses), puis fermons le canal avec pclose() et décodons le code de sortie. Un code de sortie de 0 signifie conventionnellement un succès.
Pièges courants
- Ne mélangez pas
fclose()etpclose(). Un descripteur issu depopen()doit être fermé avecpclose(), et un descripteur issu defopen()avecfclose(). pclose()est bloquante. Elle attend que le processus enfant se termine. Si la commande ne se termine jamais, votre script se bloque.- Lisez avant de fermer.
pclose()peut ignorer toute sortie tamponée non lue, donc terminez la lecture du canal en premier. - Un sens par canal. Un canal
popen()est soit lisible, soit inscriptible, mais pas les deux — pour une communication bidirectionnelle, vous avez besoin deproc_open().
Quand utiliser proc_open() à la place
popen()/pclose() sont parfaits pour une commande ponctuelle rapide où vous n'avez besoin que de sa sortie ou devez lui envoyer des données. Lorsque vous avez besoin des deux à la fois, de la séparation de stdout et stderr, d'un contrôle de l'environnement ou d'un répertoire de travail, utilisez proc_open() — il vous donne un contrôle bidirectionnel complet sur le processus lancé.
Conclusion
pclose() est le compagnon indispensable de popen() : il ferme le canal de processus, attend la fin de la commande et renvoie son code de sortie pour que vous puissiez vérifier que la commande a réussi. Associez toujours les deux, lisez le canal avant de le fermer et n'oubliez pas de décaler le statut de 8 bits vers la droite pour lire le vrai code de sortie sur les systèmes Unix. Pour tout ce qui dépasse un canal unidirectionnel, utilisez proc_open().