web-dev-qa-db-fra.com

Quelle est la différence entre les backticks, le système et l'exec de Perl?

Quelqu'un peut-il m'aider s'il vous plaît? En Perl, quelle est la différence entre:

exec "command";

et

system("command");

et

print `command`;

Existe-t-il d'autres façons d'exécuter des commandes Shell?

227
rlbond

exec

exécute une commande et ne retourne jamais . C'est comme une déclaration return dans une fonction.

Si la commande est introuvable, exec renvoie false. Il ne retourne jamais vrai, car si la commande est trouvée, elle ne retourne jamais du tout. Il est également inutile de renvoyer STDOUT, STDERR ou le statut de sortie de la commande. Vous pouvez trouver de la documentation à ce sujet dans perlfunc , car c'est une fonction.

système

exécute une commande et votre script Perl est poursuivi une fois la commande terminée.

La valeur de retour est le statut de sortie de la commande. Vous pouvez trouver de la documentation à ce sujet dans perlfunc .

backticks

comme system exécute une commande et votre script Perl est poursuivi une fois la commande terminée.

Contrairement à system, la valeur renvoyée est STDOUT de la commande. qx// est équivalent aux backticks. Vous pouvez trouver de la documentation à ce sujet dans perlop , car contrairement à system et exec, il s'agit d'un opérateur.


Autres moyens

Ce qui manque dans ce qui précède est un moyen d’exécuter une commande de manière asynchrone. Cela signifie que votre script Perl et votre commande s'exécutent simultanément. Ceci peut être accompli avec open . Il vous permet de lire STDOUT/STDERR et d'écrire dans STDIN de votre commande. Il dépend cependant de la plate-forme.

Plusieurs modules peuvent également faciliter ces tâches. Il y a IPC::Open2 et IPC::Open3 et IPC::Run, ainsi que Win32::Process::Create si vous êtes sur Windows.

256
Ludwig Weinzierl

En général, j'utilise system, open, IPC::Open2 ou IPC::Open3 en fonction de ce que je veux faire. L'opérateur qx//, bien que simple, est trop contraignant dans ses fonctionnalités pour être très utile en dehors des attaques rapides. Je trouve open beaucoup plus pratique.

system : lancez une commande et attendez qu’elle revienne

Utilisez system lorsque vous souhaitez exécuter une commande, ne vous souciez pas de sa sortie et ne voulez pas que le script Perl fasse quoi que ce soit jusqu'à la fin de la commande.

#doesn't spawn a Shell, arguments are passed as they are
system("command", "arg1", "arg2", "arg3");

ou

#spawns a Shell, arguments are interpreted by the Shell, use only if you
#want the Shell to do globbing (e.g. *.txt) for you or you want to redirect
#output
system("command arg1 arg2 arg3");

qx// ou `` : lancez une commande et capturez son STDOUT

Utilisez qx// lorsque vous souhaitez exécuter une commande, capturez ce qu'il écrit dans STDOUT et ne souhaitez pas que le script Perl fasse quoi que ce soit jusqu'à la fin de la commande.

#arguments are always processed by the Shell

#in list context it returns the output as a list of lines
my @lines = qx/command arg1 arg2 arg3/;

#in scalar context it returns the output as one string
my $output = qx/command arg1 arg2 arg3/;

exec : remplace le processus en cours par un autre processus.

Utilisez exec avec fork lorsque vous souhaitez exécuter une commande, ne vous souciez pas de sa sortie et ne voulez pas attendre qu'elle soit renvoyée. . system est vraiment juste

sub my_system {
    die "could not fork\n" unless defined(my $pid = fork);
    return waitpid $pid, 0 if $pid; #parent waits for child
    exec @_; #replace child with new process
}

Vous voudrez peut-être également lire les manuels waitpid et perlipc .

open : exécuter un processus et créer un canal vers son STDIN ou STDERR

Utilisez open lorsque vous souhaitez écrire des données dans le STDIN d'un processus ou lire des données à partir de STDOUT d'un processus (mais pas les deux en même temps).

#read from a gzip file as if it were a normal file
open my $read_fh, "-|", "gzip", "-d", $filename
    or die "could not open $filename: $!";

#write to a gzip compressed file as if were a normal file
open my $write_fh, "|-", "gzip", $filename
    or die "could not open $filename: $!";

IPC :: Open2 : lance un processus et crée un canal vers STDIN et STDOUT

Utilisez IPC::Open2 lorsque vous devez lire et écrire dans le STDIN et le STDOUT d'un processus.

use IPC::Open2;

open2 my $out, my $in, "/usr/bin/bc"
    or die "could not run bc";

print $in "5+6\n";

my $answer = <$out>;

IPC :: Open3 : exécuter un processus et créer un canal vers STDIN, STDOUT et STDERR

utilisez IPC::Open3 lorsque vous devez capturer les trois descripteurs de fichier standard du processus. J'écrirais un exemple, mais cela fonctionne essentiellement de la même manière que IPC :: Open2, mais avec un ordre légèrement différent des arguments et un troisième descripteur de fichier.

165
Chas. Owens

Permettez-moi de citer d'abord les manuels:

perldoc exec () :

La fonction exec exécute une commande système et ne renvoie jamais - utilise système au lieu de exec si tu veux qu'il revienne

système perldoc () :

Fait exactement la même chose que exec LIST, sauf que un fork est fait en premier et que le processus parent attend la fin du processus enfant.

Contrairement à exec et system, les backticks ne vous donnent pas la valeur de retour mais le STDOUT collecté.

perldoc `String` :

Une chaîne qui est (éventuellement) interpolée puis exécutée en tant que commande système avec / bin/sh ou son équivalent. Les jokers, les pipes et les redirections seront honorés. La sortie standard collectée de la commande est renvoyée ; l'erreur standard n'est pas affectée.


Alternatives:

Dans des scénarios plus complexes, où vous souhaitez extraire STDOUT, STDERR ou le code de retour, vous pouvez utiliser des modules standard bien connus tels que IPC :: Open2 et IPC :: Open .

Exemple:

use IPC::Open2;
my $pid = open2(\*CHLD_OUT, \*CHLD_IN, 'some', 'cmd', 'and', 'args');
waitpid( $pid, 0 );
my $child_exit_status = $? >> 8;

Enfin, IPC :: Run du CPAN vaut également la peine d’être examiné…

17
Benedikt Waldvogel

Quelle est la différence entre les backticks de Perl (`), system et exec?

exec -> exec "command"; ,
system -> system("command"); and 
backticks -> print `command`;

exec

exec exécute une commande et ne reprend jamais le script Perl. C'est à un script comme une déclaration return est à une fonction.

Si la commande n'est pas trouvée, exec renvoie false. Il ne retourne jamais vrai, car si la commande est trouvée, elle ne retourne jamais du tout. Il est également inutile de renvoyer STDOUT, STDERR ou le statut de sortie de la commande. Vous pouvez trouver de la documentation à ce sujet dans perlfunc, car c'est une fonction.

Par exemple.:

#!/usr/bin/Perl
print "Need to start exec command";
my $data2 = exec('ls');
print "Now END exec command";
print "Hello $data2\n\n";

Dans le code ci-dessus, il y a trois instructions print, mais étant donné que exec a quitté le script, seule la première instruction print est exécutée. De plus, la sortie de la commande exec n'est affectée à aucune variable.

Ici, vous obtenez uniquement le résultat de la première instruction print et l'exécution de la commande ls à la sortie standard.

system

system exécute une commande et votre script Perl reprend après l'exécution de la commande. La valeur de retour est le statut de sortie de la commande. Vous pouvez trouver de la documentation à ce sujet dans perlfunc.

Par exemple.:

#!/usr/bin/Perl
print "Need to start system command";
my $data2 = system('ls');
print "Now END system command";
print "Hello $data2\n\n";

Dans le code ci-dessus, il y a trois instructions print. Lorsque le script reprend après la commande system, les trois instructions d'impression sont exécutées.

De plus, le résultat de l'exécution de system est attribué à data2, mais la valeur affectée est 0 (le code de sortie de ls).

Ici, vous obtenez la sortie de la première instruction print, puis celle de la commande ls, suivie des sorties des deux dernières instructions print à la sortie standard.

piques (`)

Comme system, enfermer une commande dans des backticks exécute cette commande et votre script Perl reprend après la fin de la commande. Contrairement à system, la valeur renvoyée est STDOUT de la commande. qx// est équivalent aux backticks. Vous pouvez trouver de la documentation à ce sujet dans perlop, car contrairement à system et à exec, il s'agit d'un opérateur.

Par exemple.:

#!/usr/bin/Perl
print "Need to start backticks command";
my $data2 = `ls`;
print "Now END system command";
print "Hello $data2\n\n";

Dans le code ci-dessus, il y a trois instructions print et les trois sont en cours d'exécution. La sortie de ls ne passe pas directement à la sortie standard, mais est affectée à la variable data2 puis imprimée avec l'instruction d'impression finale.

11
linuxtestside

La différence entre 'exec' et 'system' est que exec remplace votre programme actuel par 'command' et ne retourne JAMAIS à votre programme. system, d'autre part, forks et exécute 'commande' et vous renvoie le statut de sortie de 'commande' une fois l'exécution terminée. La coche arrière exécute 'commande' puis renvoie une chaîne représentant sa sortie standard (tout ce qu'elle aurait imprimé à l'écran)

Vous pouvez également utiliser popen pour exécuter des commandes Shell et je pense qu’il existe un module Shell - "utiliser Shell" qui vous donne un accès transparent à des commandes Shell typiques.

J'espère que cela clarifie les choses pour vous.

2
Shane C. Mason