PHP shell_exec () vs exec ()

345

Ich kämpfe darum, den Unterschied zwischen shell_exec()und exec()...

Ich habe immer exec()serverseitige Befehle ausgeführt. Wann würde ich sie verwenden shell_exec()?

Ist shell_exec()nur eine Abkürzung für exec()? Es scheint dasselbe mit weniger Parametern zu sein.

Webnet
quelle
2
gutes Beispiel um die Unterschiede zu sehen ist , diese Befehle versuchen: date, whoami, ifconfig, netstat.
Es gibt auch andere Funktionen: system (), passthru ()… siehe diese verwandte Frage und insbesondere diese Antwort .
Gras Double
1
Mögliches Duplikat von PHP exec () vs system () vs passthru ()
jww

Antworten:

353

shell_execGibt den gesamten Ausgabestream als Zeichenfolge zurück. execGibt standardmäßig die letzte Zeile der Ausgabe zurück, kann jedoch alle Ausgaben als Array bereitstellen, das als zweiter Parameter angegeben wird.

Sehen

Daniel A. White
quelle
21
Wenn Sie den Exit-Wert UND die gesamte Ausgabe benötigen, ist es wahrscheinlich immer noch besser, "exec" als "shell_exec" zu verwenden. Sobald Sie den Ausgabeparameter an "exec" übergeben, wird er mit jeder Zeile der Ausgabe gefüllt. Mir scheint, "exec" kann alles von "shell_exec" und mehr :)
Preexo
4
@ daniel-a-white Ich weiß, dass dies eine alte ist, aber sie ist beliebt. Sie sollten Ihre Antwort so bearbeiten, dass sie den Kommentar von @preexo widerspiegelt. Exec () kann auch die gesamte Ausgabe zurückgeben, wenn Sie die optionalen Parameter verwenden . Unabhängig davon sollte jemand die beiden Befehle vergleichen, um herauszufinden, welche besser sind, da @preexo sagte: " Es scheint mir, dass ich exec()alles tun shell_exec()kann und mehr :) "
SimpleAnecdote
77

Hier sind die Unterschiede. Beachten Sie die Zeilenumbrüche am Ende.

> 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) ""

Beachten Sie, dass die Verwendung des Backtick-Operators identisch ist mit shell_exec().

Update: Ich sollte das letzte wirklich erklären. Wenn ich mir diese Antwort Jahre später ansehe, weiß selbst ich nicht, warum das leer war! Daniel erklärt es oben - weil execnur die letzte Zeile zurückgegeben wird und ifconfigdie letzte Zeile leer ist.

mpen
quelle
Was passiert, wenn beim Befehl ein Fehler auftritt? Ich erhalte den Fehler / Keine solche Datei oder kein solches Verzeichnis, aber wie kann ich es in einer Variablen erfassen?
Happy Coder
@AlwinAugustin: Huh? Könnte an STDERR geschrieben werden. Versuchen Sie 2>&1, am Ende Ihres Befehls STDERR zu STDOUT umzuleiten, wenn Sie sich auf einem Linux-Computer befinden.
Mpen
Ich habe es auch hinzugefügt. Trotzdem bekomme ich 0 als Wert. Ich habe einen Befehl wc -l verwendet und wenn die Datei nicht vorhanden ist, muss die Fehlermeldung "Keine solche Datei oder kein solches Verzeichnis" angezeigt werden.
Happy Coder
50

shell_exec- Führen Sie den Befehl über die Shell aus und geben Sie die vollständige Ausgabe als Zeichenfolge zurück

exec - Führen Sie ein externes Programm aus.

Der Unterschied besteht darin, dass shell_execSie eine Ausgabe als Rückgabewert erhalten.

J0HN
quelle
4
Schöne kurze Zusammenfassung! Es ist weiterhin zu beachten, dass execdie letzte Zeile der Ausgabe zurückgegeben wird. Falls gewünscht, können Sie optional ein Array als zweiten Parameter übergeben, um die vollständige Ausgabe zu erfassen, und eine Ganzzahl als dritten Parameter, um den Rückgabewert des Shell-Befehls zu erfassen, der zur Fehlerprüfung verwendet werden kann. Der größte Nachteil shell_execist, dass er null zurückgibt, wenn der Befehl fehlschlägt ODER wenn er keine Ausgabe erzeugt, sodass sein Rückgabewert nicht zuverlässig für die Fehlerprüfung verwendet werden kann.
Sean the Bean
38

Einige Unterscheidungen, die hier nicht angesprochen wurden:

  • Mit exec () können Sie eine optionale Parametervariable übergeben, die ein Array von Ausgabezeilen empfängt. In einigen Fällen kann dies Zeit sparen, insbesondere wenn die Ausgabe der Befehle bereits tabellarisch ist.

Vergleichen Sie:

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

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

Wenn die Ausgabe des Befehls hingegen xml oder json ist, ist es nicht das, was Sie möchten, jede Zeile als Teil eines Arrays zu haben, da Sie die Eingabe in eine andere Form nachbearbeiten müssen. Verwenden Sie in diesem Fall also shell_exec .

Es ist auch erwähnenswert, dass shell_exec ein Alias ​​für den backtic-Operator ist, für diejenigen, die an * nix gewöhnt sind.

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

exec unterstützt auch einen zusätzlichen Parameter, der den Rückkehrcode des ausgeführten Befehls bereitstellt:

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

Wie auf der Handbuchseite shell_exec angegeben, haben Sie keine andere Wahl, als exec zu verwenden, wenn Sie tatsächlich einen Rückkehrcode für den ausgeführten Befehl benötigen.

gview
quelle
3
Zusätzlich: execErmöglicht das Abrufen des Rückkehrcodes des Befehls (über den &$return_varParameter), shell_execbietet jedoch keine Möglichkeit, ihn abzurufen.
Mark Amery
Obwohl die akzeptierte Antwort auch richtig ist, ist diese Antwort meiner Meinung nach wichtiger. Die wahrscheinlich beste Antwort wäre eine Kombination aus beiden.
UncaAlby