PHP shell_exec () vs exec ()

345

Jestem stara się zrozumieć różnicę między shell_exec()i exec()...

Zawsze używałem exec()poleceń po stronie serwera, kiedy miałbym ich używać shell_exec()?

Czy to shell_exec()tylko skrót exec()? Wydaje się, że jest tak samo z mniejszą liczbą parametrów.

Webnet
źródło
2
Dobrym przykładem, aby zobaczyć różnice to, aby spróbować tych poleceń: date, whoami, ifconfig, netstat.
Istnieją również inne funkcje: system (), passthru ()… patrz powiązane pytanie , w szczególności ta odpowiedź .
Gras Double
1
Możliwy duplikat PHP exec () vs system () vs passthru ()
jww

Odpowiedzi:

353

shell_execzwraca cały strumień wyjściowy jako ciąg. execdomyślnie zwraca ostatni wiersz danych wyjściowych, ale może dostarczyć wszystkie dane wyjściowe jako tablicę określoną jako drugi parametr.

Widzieć

Daniel A. White
źródło
21
Jeśli potrzebujesz wartości wyjściowej ORAZ wszystkich danych wyjściowych, prawdopodobnie lepiej jest użyć „exec” zamiast „shell_exec”. Jak tylko przekażesz parametr wyjściowy do „exec”, zostanie on wypełniony każdym wierszem wyniku, wydaje mi się, że „exec” może wszystko z „shell_exec” i więcej :)
Preexo
4
@ daniel-a-white Wiem, że to stary, ale jest popularny, więc powinieneś edytować swoją odpowiedź, aby odzwierciedlić komentarz @preexo - exec () ma również możliwość zwrócenia całego wyniku, jeśli użyjesz jego opcjonalnych parametrów . Ponadto, niepowiązany, ktoś powinien porównać te dwa polecenia, aby zobaczyć, co jest lepsze, ponieważ @preexo powiedział: „ wydaje mi się, że exec()mogę [zrobić] wszystko shell_exec()[może,] i więcej :)
SimpleAnecdote
77

Oto różnice. Zwróć uwagę na nowe linie na końcu.

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

Zauważ, że użycie operatora backtick jest identyczne jak shell_exec().

Aktualizacja: Naprawdę powinienem wyjaśnić to ostatnie. Patrząc na tę odpowiedź wiele lat później, nawet nie wiem, dlaczego to wyszło puste! Daniel wyjaśnia to powyżej - to dlatego, że execzwraca tylko ostatnią linię, a ifconfigostatnia linia jest pusta.

mpen
źródło
co się stanie, jeśli wystąpi jeden błąd w poleceniu ..? Otrzymuję błąd / Brak takiego pliku lub katalogu, ale jak mogę go przechwycić do zmiennej ????
Szczęśliwy Coder,
@AlwinAugustin: Huh? Może być zapisywane do STDERR. Spróbuj dodać 2>&1na końcu polecenia, aby przekierować STDERR do STDOUT, jeśli korzystasz z komputera z systemem Linux.
mpen
Dodałem to również. Ale wciąż otrzymuję 0 jako wartość. Użyłem jednej komendy wc -l, a jeśli pliku nie ma, muszę otrzymać komunikat o błędzie „Brak takiego pliku lub katalogu”.
Szczęśliwy Coder,
50

shell_exec- Wykonaj polecenie przez powłokę i zwróć pełne dane wyjściowe jako ciąg

exec - Uruchom program zewnętrzny.

Różnica polega na tym, shell_execże otrzymujesz wynik jako wartość zwracaną.

J0HN
źródło
4
Ładne, zwięzłe podsumowanie! Należy jeszcze zauważyć, że execzwraca ostatni wiersz wyniku. W razie potrzeby można opcjonalnie przekazać tablicę jako drugi parametr do przechwycenia pełnego wyniku, a liczbę całkowitą jako trzeci parametr do przechwycenia wartości zwracanej przez komendę powłoki, której można użyć do sprawdzania błędów. Największym minusem shell_execjest to, że zwraca wartość null, jeśli polecenie nie powiedzie się LUB jeśli nie generuje żadnych danych wyjściowych, więc jego wartość zwracana nie może być niezawodnie wykorzystana do sprawdzania błędów.
Sean the Bean
38

Kilka wyróżnień, których nie poruszono tutaj:

  • Za pomocą exec () możesz przekazać opcjonalną zmienną param, która otrzyma tablicę linii wyjściowych. W niektórych przypadkach może to zaoszczędzić czas, zwłaszcza jeśli dane wyjściowe poleceń są już tabelaryczne.

Porównać:

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

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

I odwrotnie, jeśli wynikiem działania polecenia jest xml lub json, to umieszczenie każdej linii jako części tablicy nie jest tym, czego potrzebujesz, ponieważ musisz przetworzyć dane wejściowe w innej formie, więc w takim przypadku użyj shell_exec .

Warto również zauważyć, że shell_exec jest aliasem dla operatora backtic, dla tych używanych do * nix.

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

exec obsługuje również dodatkowy parametr, który zapewni kod powrotu z wykonanego polecenia:

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

Jak zauważono na stronie podręcznika shell_exec, kiedy faktycznie potrzebujesz kodu powrotu z wykonywanej komendy, nie masz innego wyjścia, jak użyć exec.

gview
źródło
3
Dodatkowo: execpozwala uzyskać kod powrotu polecenia (za pomocą &$return_varparametru), ale shell_execnie zapewnia możliwości uzyskania go.
Mark Amery
Chociaż zaakceptowana odpowiedź jest również poprawna, moim zdaniem ta odpowiedź jest ważniejsza. Prawdopodobnie najlepszą odpowiedzią byłoby połączenie obu.
UncaAlby,