PHP shell_exec () vs exec ()

345

J'ai du mal à comprendre la différence entre shell_exec()et exec()...

Je l'ai toujours utilisé exec()pour exécuter des commandes côté serveur, quand devrais-je utiliser shell_exec()?

Est-ce shell_exec()juste un raccourci pour exec()? Il semble que ce soit la même chose avec moins de paramètres.

Webnet
la source
2
bon exemple pour voir les différences est d'essayer ces commandes: date, whoami, ifconfig, netstat.
Il y a aussi d'autres fonctions: system (), passthru ()… voir cette question connexe , et en particulier cette réponse .
Gras Double
1
Duplication possible de PHP exec () vs system () vs passthru ()
jww

Réponses:

353

shell_execrenvoie tout le flux de sortie sous forme de chaîne. execrenvoie la dernière ligne de la sortie par défaut, mais peut fournir toutes les sorties sous forme de tableau spécifié comme deuxième paramètre.

Voir

Daniel A. White
la source
21
Si vous avez besoin de la valeur de sortie ET de toutes les sorties, vous êtes probablement encore mieux d'utiliser "exec" plutôt que "shell_exec". Dès que vous passez le paramètre de sortie à "exec", il sera rempli avec chaque ligne de la sortie, il me semble que "exec" peut tout de "shell_exec" et plus :)
Preexo
4
@ daniel-a-white Je sais que c'est une ancienne, mais elle est populaire, vous devez donc modifier votre réponse pour refléter le commentaire fait par @preexo - exec () a également la possibilité de renvoyer la sortie entière si vous utilisez ses paramètres facultatifs . De plus, sans relation, quelqu'un devrait comparer les deux commandes pour voir laquelle est la meilleure parce que @preexo a dit " il me semble qu'il exec()peut [faire] tout shell_exec()[peut,] et plus :) "
SimpleAnecdote
77

Voici les différences. Notez les nouvelles lignes à la fin.

> shell_exec('date')
string(29) "Wed Mar  6 14:18:08 PST 2013\n"
> exec('date')
string(28) "Wed Mar  6 14:18:12 PST 2013"

> shell_exec('whoami')
string(9) "mark\n"
> exec('whoami')
string(8) "mark"

> shell_exec('ifconfig')
string(1244) "eth0      Link encap:Ethernet  HWaddr 10:bf:44:44:22:33  \n          inet addr:192.168.0.90  Bcast:192.168.0.255  Mask:255.255.255.0\n          inet6 addr: fe80::12bf:ffff:eeee:2222/64 Scope:Link\n          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1\n          RX packets:16264200 errors:0 dropped:1 overruns:0 frame:0\n          TX packets:7205647 errors:0 dropped:0 overruns:0 carrier:0\n          collisions:0 txqueuelen:1000 \n          RX bytes:13151177627 (13.1 GB)  TX bytes:2779457335 (2.7 GB)\n"...
> exec('ifconfig')
string(0) ""

Notez que l'utilisation de l' opérateur backtick est identique à shell_exec().

Mise à jour: je devrais vraiment expliquer ce dernier. En regardant cette réponse des années plus tard, même je ne sais pas pourquoi cela est resté vierge! Daniel l'explique ci-dessus - c'est parce execque ne renvoie que la dernière ligne, et ifconfigla dernière ligne est vide.

mpen
la source
que se passe-t-il s'il y a une erreur avec la commande ..? J'obtiens l'erreur / Aucun fichier ou répertoire de ce type, mais comment puis-je le capturer dans une variable ????
Happy Coder
@AlwinAugustin: Hein? Pourrait être écrit à STDERR. Essayez d'ajouter 2>&1à la fin de votre commande pour rediriger STDERR vers STDOUT si vous êtes sur une machine Linux.
mpen
Je l'ai ajouté également. Mais je reçois toujours 0 comme valeur. J'ai utilisé une commande wc -l et si le fichier n'est pas là, j'ai besoin d'obtenir le message d'erreur disant Aucun fichier ou répertoire.
Happy Coder
50

shell_exec- Exécuter la commande via le shell et retourner la sortie complète sous forme de chaîne

exec - Exécutez un programme externe.

La différence est que shell_execvous obtenez la sortie comme valeur de retour.

J0HN
la source
4
Beau résumé succinct! Il faut tout de même noter que execretourne la dernière ligne de la sortie. Si vous le souhaitez, vous pouvez éventuellement transmettre un tableau comme deuxième paramètre pour capturer la sortie complète, et un entier comme troisième paramètre pour capturer la valeur de retour de la commande shell, qui peut être utilisée pour la vérification des erreurs. Le plus gros inconvénient shell_execest qu'il retourne null si la commande échoue OU s'il ne produit aucune sortie, donc sa valeur de retour ne peut pas être utilisée de manière fiable pour la vérification des erreurs.
Sean the Bean
38

Quelques distinctions qui n'ont pas été abordées ici:

  • Avec exec (), vous pouvez passer une variable param optionnelle qui recevra un tableau de lignes de sortie. Dans certains cas, cela peut gagner du temps, surtout si la sortie des commandes est déjà tabulaire.

Comparer:

exec('ls', $out);
var_dump($out);
// Look an array

$out = shell_exec('ls');
var_dump($out);
// Look -- a string with newlines in it

Inversement, si la sortie de la commande est xml ou json, avoir chaque ligne dans un tableau n'est pas ce que vous voulez, car vous devrez post-traiter l'entrée sous une autre forme, alors dans ce cas, utilisez shell_exec .

Il convient également de souligner que shell_exec est un alias pour l'opérateur backtic, pour ceux utilisés pour * nix.

$out = `ls`;
var_dump($out);

exec prend également en charge un paramètre supplémentaire qui fournira le code retour de la commande exécutée:

exec('ls', $out, $status);
if (0 === $status) {
    var_dump($out);
} else {
    echo "Command failed with status: $status";
}

Comme indiqué dans la page de manuel shell_exec, lorsque vous avez réellement besoin d'un code retour de la commande en cours d'exécution, vous n'avez pas d'autre choix que d'utiliser exec.

gview
la source
3
De plus: execvous permet d'obtenir le code retour de la commande (via le &$return_varparamètre), tout en shell_execne fournissant aucun moyen de l'obtenir.
Mark Amery
Bien que la réponse acceptée soit également correcte, à mon avis, cette réponse est plus importante. La meilleure réponse serait probablement la combinaison des deux.
UncaAlby