L'interaction avec des programmes externes est une caractéristique critique de Perl, héritée depuis la création du langage en 1987 pour les tâches d'administration système et l'automatisation des routines shell. Perl propose plusieurs façons d'exécuter une commande externe : l'opérateur system, les backticks (``) ou qx//, la fonction open avec un pipe, et les wrappers modulaires comme IPC::Open3.
Le principal problème lors du lancement de processus externes est d'obtenir correctement la sortie (stdout et stderr), de gérer les erreurs de lancement, la sécurité des paramètres (pour éviter les injections), ainsi que la différence entre l'exécution synchrone et asynchrone.
La solution réside dans le choix de la méthode appropriée pour la tâche spécifique. Pour les commandes simples, on utilise system ou les backticks, pour les cas complexes — les modules IPC::* :
Exemple de code (lecture de la sortie de la commande et gestion des erreurs) :
my $command = 'ls -l /tmp'; my $output = qx{$command}; if ($? == -1) { die "Erreur de lancement : $!"; } elsif ($? & 127) { warn sprintf "La commande s'est terminée avec le signal %d", ($? & 127); } else { print "Sortie : $output"; }
Caractéristiques clés :
Quelle est la différence entre system et exec en Perl ?
Réponse : system lance une commande dans un processus externe et retourne le contrôle à Perl après son achèvement, alors que exec remplace complètement le processus Perl en cours par le programme exécuté, le code Perl suivant n'est pas exécuté.
Exemple :
system('echo Hello'); exec('ls', '-l'); # Tout, le script Perl est remplacé par ls, Perl ne fonctionne plus ensuite
Peut-on passer en toute sécurité des variables utilisateur dans des commandes shell ?
Réponse : Seulement en utilisant une liste d'arguments (pas des chaînes) et en évitant l'interpolation dans le shell. Sinon, une injection de commande est possible.
# En toute sécurité : system("ls", "-l", $user_supplied_dir); # Dangereux : system("ls -l $user_supplied_dir");
Comment obtenir à la fois stdout et stderr d'une commande externe ?
Réponse : La méthode fiable est d'utiliser IPC::Open3 ou de rediriger stderr vers stdout au niveau du shell :
my $out = qx{ls /notexists 2>&1};
ou via IPC::Open3 (méthode plus universelle et sophistiquée).
Un admin passe une valeur saisie par l'utilisateur via system("rm -rf $dir").
Avantages :
Inconvénients :
Utilisation de system('rm', '-rf', $dir), $dir est validé et journalisation mise en place.
Avantages :
Inconvénients :