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

312

Jakie są różnice?

Czy jest określona sytuacja lub powód każdej funkcji? Jeśli tak, czy możesz podać przykłady takich sytuacji?

PHP.net mówi, że są one używane do uruchamiania programów zewnętrznych. patrz odniesienie Z przykładów, które widzę, nie widzę żadnej oczywistej różnicy.

Gdybym miał po prostu uruchomić skrypt (bash lub python), jakiej funkcji polecasz mi użyć?

codingbear
źródło
16
Istnieje również proc_open()i popen(), które pozwalają na wyższy stopień kontroli nad procesem spawnowania.
Christian

Odpowiedzi:

195

Mają nieco inne cele.

  • exec() służy do wywołania polecenia systemowego i być może samodzielnego radzenia sobie z danymi wyjściowymi.
  • system() służy do wykonania polecenia systemowego i natychmiastowego wyświetlenia wyniku - prawdopodobnie tekstu.
  • passthru() służy do wykonania komendy systemowej, od której chcesz uzyskać surowy zwrot - prawdopodobnie coś binarnego.

Niezależnie od tego sugeruję, abyś nie używał żadnego z nich. Wszystkie produkują wysoce nieprzenośny kod.

Kalium
źródło
147
Czasami przenośność musi być poświęcona dla funkcjonalności. Jest kilka rzeczy, których PHP po prostu nie potrafi dobrze.
Frank Crook,
30
@Kalium: czy możesz rozwinąć swoje oświadczenie? samo stwierdzenie niejasnych statystyk procentowych mnie nie przekonuje. Uważam, że używanie wywołań systemowych do wykonywania skryptów jest całkowicie w porządku, o ile cała aplikacja nie zależy od kilku skryptów w zapleczu.
codingbear
46
@Christian izkata@izein:~$ dir -bash: dir: command not found- FreeBSD
Izkata
5
@OZ_ Doszedłem do sytuacji, w której musiałem wykonać bardzo drogie obliczenia. Żaden moduł PHP nie był (jest) do tego dostępny. Napisałem własny program w języku C i wywołuję go za pomocą passthru (). Czasami przenośność może być mniej ważna niż inne rzeczy. Zależy od projektu.
Paolo
9
Ponadto, jest to błędne myślenie, że PHP jest przenośny, tak długo, jak można uniknąć exec, system, passthru. Kod PHP jest zależny od środowiska, w którym działa, a wiele błędów bezpieczeństwa wynika z tego, że nie bierze się tego pod uwagę. Oto szybki przykład: stackoverflow.com/questions/3003145/…
Pacerier
131

Jak wynika z http://php.net/ && Chipmunkninja :

System () Funkcja

Funkcja systemowa w PHP pobiera argument ciągu z poleceniem do wykonania, a także wszelkie argumenty, które chcesz przekazać do tego polecenia. Ta funkcja wykonuje określone polecenie i zrzuca dowolny wynikowy tekst do strumienia wyjściowego (wyjście HTTP w sytuacji serwera WWW lub konsola, jeśli używasz PHP jako narzędzia wiersza poleceń). Zwrot tej funkcji jest ostatnim wierszem wyjścia programu, jeśli emituje tekst.

Exec () Funkcja

Funkcja systemowa jest dość użyteczna i wydajna, ale jednym z największych problemów jest to, że cały wynikowy tekst z programu trafia bezpośrednio do strumienia wyjściowego. Będą sytuacje, w których możesz chcieć sformatować wynikowy tekst i wyświetlić go w inny sposób lub w ogóle go nie wyświetlić.

W tym celu funkcja exec w PHP jest doskonale dostosowana. Zamiast automatycznego zrzutu całego tekstu generowanego przez program wykonywany do strumienia wyjściowego, daje on możliwość umieszczenia tego tekstu w tablicy zwróconej w drugim parametrze do funkcji:

Shell_exec () Funkcja

Większość programów, które do tej pory wykonywaliśmy, były mniej więcej prawdziwymi programami1. Jednak środowisko, w którym działają użytkownicy systemów Windows i Unix, jest znacznie bogatsze niż to. Użytkownicy systemu Windows mają możliwość korzystania z programu Windows Command Prompt, cmd.exe Program ten jest znany jako powłoka poleceń.

Pośredni () Funkcja

Jedną z fascynujących funkcji PHP, podobnych do tych, które widzieliśmy do tej pory, jest funkcja passthru. Ta funkcja, podobnie jak inne, uruchamia program, który mu powiesz. Następnie przechodzi do natychmiastowego wysyłania nieprzetworzonych danych wyjściowych z tego programu do strumienia wyjściowego, z którym PHP obecnie pracuje (tj. Albo HTTP w scenariuszu serwera WWW, albo powłokę w wersji PHP wiersza poleceń).

Proc_open () Funkcja i popen () funkcja

proc_open () jest podobny do popen (), ale zapewnia znacznie większy stopień kontroli nad wykonywaniem programu. cmd to polecenie wykonywane przez powłokę. descriptorspec to tablica indeksowana, w której klucz reprezentuje numer deskryptora, a wartość reprezentuje sposób, w jaki PHP przekaże ten deskryptor procesowi potomnemu. potoki zostaną ustawione na indeksowaną tablicę wskaźników plików, które odpowiadają końcowi PHP wszystkich tworzonych potoków. Wartość zwracana jest zasobem reprezentującym proces; powinieneś go zwolnić za pomocą proc_close (), kiedy skończysz.

Dinesh Saini
źródło
6
Szybkość wykonywania shell_exec jest większa niż w przypadku innej alternatywy.
Dinesh Saini
29
Powinieneś wspomnieć, że skopiowałeś swoją odpowiedź bezpośrednio z ChipmunkNinja .
TachyonVortex
7
@TachyonVortex na szczęście skopiował odpowiedź dosłownie, ponieważ ChipmunkNinja już nie istnieje.
Phileo99
2
Kopia tego artykułu znajduje się w maszynie powrotnej
bagonyi
2
Co z popenem i proc_openem?
CMCDragonkai
103

Poprzednie odpowiedzi wydają się trochę mylące lub niekompletne, więc oto tabela różnic ...

+----------------+-----------------+----------------+----------------+
|    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             |
+----------------+-----------------+----------------+----------------+
  • „Wyświetla dane wyjściowe” oznacza, że ​​przesyła strumieniowo dane wyjściowe do przeglądarki (lub dane wyjściowe z wiersza poleceń, jeśli są uruchamiane z wiersza poleceń).
  • „Can Get Output” oznacza, że ​​możesz uzyskać wynik polecenia i przypisać go do zmiennej PHP.
  • „Kod wyjścia” to specjalna wartość zwracana przez polecenie (zwana również „statusem zwrotu”). Zero zwykle oznacza, że ​​się powiodło, inne wartości to zwykle kody błędów.

Inne różne rzeczy, o których należy pamiętać:

  • Shell_exec () i operator backticks robią to samo.
  • Istnieją również proc_open () i popen (), które pozwalają na interaktywny odczyt / zapis strumieni za pomocą komendy wykonawczej.
  • Dodaj „2> i 1” do ciągu poleceń, jeśli chcesz również przechwytywać / wyświetlać komunikaty o błędach.
  • Użyj escapeshellcmd (), aby uniknąć argumentów poleceń, które mogą zawierać problematyczne znaki.
  • Jeśli przekażemy zmienną wyjściową $ do exec () w celu zapisania wyniku, jeśli wyjście $ nie jest puste, dołącza do niego nowe wyjście. Może więc być konieczne najpierw rozbrojenie (wyjście $).
Orrd
źródło
które z nich mogą wykonać plik php?
John, dlaczego
1
@ johnywhy none per se - chyba że wyraźnie wywołujesz php cli lub coś takiego. Przypuszczam, że chcesz includei przyjaciele
Hagen von Eitzen
21

Wszystko sprowadza się do sposobu, w jaki chcesz obsługiwać dane wyjściowe, które może zwrócić polecenie, oraz tego, czy chcesz, aby skrypt PHP czekał na zakończenie programu odbierającego, czy nie.

  • exec wykonuje polecenie i przekazuje dane do programu wywołującego (lub zwraca je w zmiennej opcjonalnej).

  • passthrujest podobny do exec()funkcji, ponieważ wykonuje polecenie. Tej funkcji należy używać zamiast danych wyjściowych komendy Unix exec()lub w system()przypadku danych binarnych, które należy przekazać bezpośrednio z powrotem do przeglądarki.

  • system wykonuje zewnętrzny program i wyświetla dane wyjściowe, ale tylko ostatni wiersz.

Jeśli musisz wykonać polecenie i wszystkie dane z polecenia zostały przekazane bezpośrednio z powrotem bez żadnych zakłóceń, użyj passthru()funkcji.

Cody Caughlan
źródło
8

Jeśli uruchamiasz skrypt PHP z wiersza polecenia, passthru()ma jedną dużą zaletę. Pozwoli Ci wykonywanie skryptów / programów, takich jak vim, dialogitp, dając tych programów Manetka i powrocie do skryptu tylko wtedy, gdy są one wykonane.

Jeśli użyjesz system()lub wykonasz exec()te skrypty / programy, to po prostu nie zadziała.

Haczyka: Z jakiegoś powodu, nie można wykonać lessz passthru()PHP.

Matt
źródło
1
Nie rozumiem co mówisz. Możesz uruchamiać programy zarówno z interfejsu CLI, jak i (F) CGI (a także mod_php). Mogą obowiązywać ograniczenia systemowe, takie jak selinux. Ale dobrze skonfigurowany system będzie selektywnie wyłączał te. Oczywiście współużytkowany host to inna historia, ale nie zapewnisz wspólnego środowiska cenionym klientom, nie?
Christian