PHP exec () vs system () vs passthru ()

312

Was sind die Unterschiede?

Gibt es für jede Funktion eine bestimmte Situation oder einen bestimmten Grund? Wenn ja, können Sie einige Beispiele für diese Situationen nennen?

PHP.net sagt, dass sie verwendet werden, um externe Programme auszuführen. siehe Referenz Aus den Beispielen, die ich sehe, sehe ich keinen offensichtlichen Unterschied.

Wenn ich einfach ein Skript (Bash oder Python) ausführen würde, welche Funktion empfehlen Sie mir?

Codingbear
quelle
16
Es gibt auch proc_open()und popen(), die beide ein höheres Maß an Kontrolle über den erzeugten Prozess ermöglichen.
Christian

Antworten:

195

Sie haben etwas andere Zwecke.

  • exec() dient dazu, einen Systembefehl aufzurufen und die Ausgabe möglicherweise selbst zu bearbeiten.
  • system() dient zur Ausführung eines Systembefehls und zur sofortigen Anzeige der Ausgabe - vermutlich von Text.
  • passthru() dient zum Ausführen eines Systembefehls, von dem Sie die rohe Rückkehr wünschen - vermutlich etwas Binäres.

Unabhängig davon schlage ich vor, dass Sie keine von ihnen verwenden. Sie alle produzieren höchst unsportierbaren Code.

Kalium
quelle
147
Manchmal muss die Portabilität für die Funktionalität geopfert werden. Es gibt einige Dinge, die PHP einfach nicht gut kann.
Frank Crook
30
@ Kalium: Können Sie Ihre Aussage näher erläutern? Nur einige vage prozentuale Statistiken anzugeben, überzeugt mich nicht. Ich glaube, dass die Verwendung von Systemaufrufen zum Ausführen von Skripten völlig in Ordnung ist, solange die gesamte Anwendung nicht von einer Reihe von Skripten im Back-End abhängt.
Codingbear
46
@Christian izkata@izein:~$ dir -bash: dir: command not found- FreeBSD
Izkata
5
@OZ_ Ich bin zu einer Situation gekommen, in der ich sehr teure Berechnungen durchführen musste. Dafür war (ist) kein PHP-Modul verfügbar. Ich habe mein eigenes C-Programm geschrieben und es mit passthru () aufgerufen. Manchmal ist Portabilität weniger wichtig als andere Dinge. Kommt auf das Projekt an.
Paolo
9
Außerdem ist es ein Irrtum zu glauben , dass PHP tragbar ist , solange Sie vermeiden exec, system, passthru. PHP-Code hängt von der Umgebung ab, in der er ausgeführt wird, und viele Sicherheitslücken sind darauf zurückzuführen, dass dies nicht berücksichtigt wird. Hier ist ein kurzes Beispiel: stackoverflow.com/questions/3003145/…
Pacerier
131

Wie aus http://php.net/ && Chipmunkninja entnommen :

Die system () Funktion

Die Systemfunktion in PHP verwendet ein Zeichenfolgenargument mit dem auszuführenden Befehl sowie alle Argumente, die Sie an diesen Befehl übergeben möchten. Diese Funktion führt den angegebenen Befehl aus und speichert den resultierenden Text im Ausgabestream (entweder die HTTP-Ausgabe in einer Webserversituation oder die Konsole, wenn Sie PHP als Befehlszeilentool ausführen). Die Rückgabe dieser Funktion ist die letzte Ausgabezeile des Programms, wenn es eine Textausgabe ausgibt.

Die exec () Funktion

Die Systemfunktion ist sehr nützlich und leistungsstark, aber eines der größten Probleme dabei ist, dass der gesamte aus dem Programm resultierende Text direkt in den Ausgabestream gelangt. Es wird Situationen geben, in denen Sie den resultierenden Text möglicherweise formatieren und auf andere Weise oder gar nicht anzeigen möchten.

Dafür ist die Exec-Funktion in PHP perfekt angepasst. Anstatt den gesamten vom ausgeführten Programm generierten Text automatisch in den Ausgabestream zu kopieren, haben Sie die Möglichkeit, diesen Text in ein Array einzufügen, das im zweiten Parameter an die Funktion zurückgegeben wird:

Die Funktion shell_exec ()

Die meisten Programme, die wir bisher ausgeführt haben, waren mehr oder weniger echte Programme1. Die Umgebung, in der Windows- und Unix-Benutzer arbeiten, ist jedoch viel umfangreicher. Windows-Benutzer haben die Möglichkeit, das Windows-Eingabeaufforderungsprogramm cmd.exe zu verwenden. Dieses Programm wird als Befehlsshell bezeichnet.

Die Funktion passthru ()

Eine faszinierende Funktion, die PHP ähnlich wie bisher bietet, ist die Durchgangsfunktion. Diese Funktion führt wie die anderen das Programm aus, das Sie anweisen. Anschließend wird jedoch sofort die Rohausgabe dieses Programms an den Ausgabestream gesendet, mit dem PHP derzeit arbeitet (dh entweder HTTP in einem Webserverszenario oder die Shell in einer Befehlszeilenversion von PHP).

Die proc_open () Funktion und popen () Funktion

proc_open () ähnelt popen (), bietet jedoch ein viel höheres Maß an Kontrolle über die Programmausführung. cmd ist der Befehl, der von der Shell ausgeführt werden soll. Descriptorspec ist ein indiziertes Array, bei dem der Schlüssel die Deskriptornummer darstellt und der Wert angibt, wie PHP diesen Deskriptor an den untergeordneten Prozess weitergibt. Pipes werden auf ein indiziertes Array von Dateizeigern gesetzt, die dem PHP-Ende aller erstellten Pipes entsprechen. Der Rückgabewert ist eine Ressource, die den Prozess darstellt. Sie sollten es mit proc_close () freigeben, wenn Sie damit fertig sind.

Dinesh Saini
quelle
6
Die Ausführungsgeschwindigkeit von shell_exec ist schneller als bei anderen Alternativen.
Dinesh Saini
29
Sie sollten erwähnen, dass Sie Ihre Antwort direkt von ChipmunkNinja kopiert haben .
TachyonVortex
7
@TachyonVortex Zum Glück hat er die Antwort wörtlich kopiert, da ChipmunkNinja nicht mehr existiert.
Phileo99
2
Es gibt eine Kopie dieses Artikels in der Wayback-Maschine: web.archive.org/web/20130809032648/http://chipmunkninja.com/…
bagonyi
2
Was ist mit popen und proc_open?
CMCDragonkai
103

Die vorherigen Antworten scheinen alle etwas verwirrend oder unvollständig zu sein. Hier ist eine Tabelle der Unterschiede ...

+----------------+-----------------+----------------+----------------+
|    Command     | Displays Output | Can Get Output | Gets Exit Code |
+----------------+-----------------+----------------+----------------+
| system()       | Yes (as text)   | Last line only | Yes            |
| passthru()     | Yes (raw)       | No             | Yes            |
| exec()         | No              | Yes (array)    | Yes            |
| shell_exec()   | No              | Yes (string)   | No             |
| backticks (``) | No              | Yes (string)   | No             |
+----------------+-----------------+----------------+----------------+
  • "Anzeige der Ausgabe" bedeutet, dass die Ausgabe an den Browser (oder die Befehlszeilenausgabe, wenn sie über eine Befehlszeile ausgeführt wird) gestreamt wird.
  • "Can Get Output" bedeutet, dass Sie die Ausgabe des Befehls abrufen und einer PHP-Variablen zuweisen können.
  • Der "Exit-Code" ist ein spezieller Wert, der vom Befehl zurückgegeben wird (auch als "Rückgabestatus" bezeichnet). Null bedeutet normalerweise, dass es erfolgreich war, andere Werte sind normalerweise Fehlercodes.

Andere verschiedene Dinge, die Sie beachten sollten:

  • Der Shell_exec () und der Backticks-Operator machen dasselbe.
  • Es gibt auch proc_open () und popen (), mit denen Sie Streams mit einem ausführenden Befehl interaktiv lesen / schreiben können.
  • Fügen Sie der Befehlszeichenfolge "2> & 1" hinzu, wenn Sie auch Fehlermeldungen erfassen / anzeigen möchten.
  • Verwenden Sie escesheshellcmd (), um Befehlsargumente zu umgehen, die möglicherweise Problemzeichen enthalten.
  • Wenn Sie eine $ output-Variable an exec () übergeben, um die Ausgabe zu speichern, und wenn $ output nicht leer ist, wird die neue Ausgabe daran angehängt. Daher müssen Sie möglicherweise zuerst die Einstellung ($ output) deaktivieren.
orrd
quelle
Welche können eine PHP-Datei ausführen?
Johny, warum
1
@johnywhy keine per se - es sei denn, Sie rufen ausdrücklich die PHP-CLI oder dergleichen auf. Ich nehme an, Sie wollen includeund Freunde
Hagen von Eitzen
21

Es kommt wirklich darauf an, wie Sie mit der Ausgabe umgehen möchten, die der Befehl möglicherweise zurückgibt, und ob Ihr PHP-Skript warten soll, bis das Angerufene-Programm beendet ist oder nicht.

  • exec führt einen Befehl aus und übergibt die Ausgabe an den Aufrufer (oder gibt sie in einer optionalen Variablen zurück).

  • passthruist der exec()Funktion insofern ähnlich , als sie einen Befehl ausführt. Diese Funktion sollte anstelle von exec()oder verwendet werden, system()wenn die Ausgabe des Unix-Befehls Binärdaten sind, die direkt an den Browser zurückgegeben werden müssen.

  • system führt ein externes Programm aus und zeigt die Ausgabe an, aber nur die letzte Zeile.

Wenn Sie einen Befehl ausführen müssen und alle Daten des Befehls ohne Störung direkt zurückgeben müssen, verwenden Sie die passthru()Funktion.

Cody Caughlan
quelle
8

Wenn Sie Ihr PHP-Skript über die Befehlszeile ausführen, passthru()hat dies einen großen Vorteil. Damit können Sie Skripte / Programme wie z vim.dialog usw., diese Programme Griff - Steuerung und die Rückkehr in das Skript zu lassen , nur wenn sie fertig sind.

Wenn Sie system()oder verwendenexec() diese Skripte / Programme ausführen, funktioniert dies einfach nicht.

Gotcha: Aus irgendeinem Grund können Sie nicht lessmit passthru()in PHP ausführen .

Matt
quelle
1
Ich verstehe nicht, was du sagst. Sie können Programme sowohl über CLI als auch über (F) CGI (sowie über mod_php) ausführen. Es kann systembedingte Einschränkungen geben, wie z. B. Selinux. Bei einem gut eingerichteten System werden diese jedoch selektiv deaktiviert. Natürlich ist ein gemeinsamer Host eine andere Geschichte, aber Sie werden auch geschätzten Kunden keine gemeinsame Umgebung anbieten , oder?
Christian