PHP shell_exec () против exec ()

345

Я изо всех сил пытаюсь понять разницу между shell_exec()и exec()...

Я всегда использовал exec()для выполнения команд на стороне сервера, когда я буду использовать shell_exec()?

Это shell_exec()просто сокращение для exec()? Похоже, то же самое с меньшим количеством параметров.

Webnet
источник
2
хороший пример , чтобы увидеть различие, чтобы попробовать эти команды: date, whoami, ifconfig, netstat.
Есть и другие функции: system (), passthru ()… см. Этот связанный вопрос , и, в частности, этот ответ .
Двойной Гра
1
Возможный дубликат PHP exec () против system () против passthru ()
августа

Ответы:

353

shell_execвозвращает весь выходной поток в виде строки. execпо умолчанию возвращает последнюю строку вывода, но может предоставить весь вывод в виде массива, указанного в качестве второго параметра.

Видеть

Даниэль А. Уайт
источник
21
Если вам нужно значение выхода И все выходные данные, вам, вероятно, все же лучше использовать «exec», а не «shell_exec». Как только вы передадите выходной параметр в «exec», он будет заполнен каждой строкой вывода, мне кажется, что «exec» может все, что в «shell_exec» и более :)
Preexo
4
@ daniel-a-white Я знаю, что это старый, но он популярен, поэтому вы должны отредактировать свой ответ, чтобы отразить комментарий, сделанный @preexo - exec () также может возвращать весь вывод, если вы используете его необязательные параметры , Кроме того, независимо от того, кто-то должен сравнить две команды, чтобы увидеть, какая из них лучше, потому что @preexo сказал: « Мне кажется, я exec()могу [сделать] все shell_exec()[можно,] и даже больше :) »
SimpleAnecdote
77

Вот различия. Обратите внимание на новые строки в конце.

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

Обратите внимание, что использование оператора backtick идентично shell_exec().

Обновление: я действительно должен объяснить это последнее. Глядя на этот ответ спустя годы, даже я не знаю, почему это оказалось пустым! Даниэль объясняет это выше - это потому, что execвозвращает только последнюю строку, а ifconfigпоследняя строка оказывается пустой.

mpen
источник
что произойдет, если с командой возникнет одна ошибка ..? Я получаю сообщение об ошибке / Нет такого файла или каталога, но как я могу записать его в переменную ????
Счастливый кодер
@AlwinAugustin: А? Может быть, пишут в STDERR. Попробуйте добавить 2>&1в конец команды, чтобы перенаправить STDERR в STDOUT, если вы работаете на машине с Linux.
mpen
Я добавил это также. Но все равно я получаю 0 в качестве значения. Я использовал одну команду wc -l, и если файла нет, мне нужно получить сообщение об ошибке, говорящее, что нет такого файла или каталога.
Счастливый кодер
50

shell_exec- Выполнить команду через оболочку и вернуть весь вывод в виде строки

exec - Выполнить внешнюю программу.

Разница в том, что shell_execвы получаете вывод в качестве возвращаемого значения.

J0HN
источник
4
Хорошее краткое резюме! Следует еще отметить, что execвозвращает последнюю строку вывода. При желании вы можете при желании передать массив в качестве второго параметра, чтобы захватить весь вывод, и целое число в качестве третьего параметра, чтобы захватить возвращаемое значение команды оболочки, которое можно использовать для проверки ошибок. Самым большим недостатком shell_execявляется то, что она возвращает ноль, если команда не выполняется ИЛИ, если она не выдает никаких выходных данных, поэтому ее возвращаемое значение нельзя надежно использовать для проверки ошибок.
Шон Боб
38

Пара различий, которые не были затронуты здесь:

  • С помощью exec () вы можете передать необязательную переменную param, которая получит массив выходных строк. В некоторых случаях это может сэкономить время, особенно если выходные команды уже представлены в виде таблицы.

Для сравнения:

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

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

И наоборот, если выходные данные команды - xml или json, то каждая строка как часть массива - это не то, что вам нужно, так как вам нужно будет постобработать ввод в какую-то другую форму, поэтому в этом случае используйте shell_exec ,

Также стоит отметить, что shell_exec является псевдонимом для оператора backtic, для тех, которые используются для * nix.

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

exec также поддерживает дополнительный параметр, который предоставит код возврата от выполненной команды:

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

Как отмечено на странице справки shell_exec, когда вам действительно требуется код возврата от выполняемой команды, у вас нет другого выбора, кроме как использовать exec.

GView
источник
3
Дополнительно: execпозволяет получить обратный код команды (через &$return_varпараметр), в то время как shell_execне дает никакой возможности получить его.
Марк Эмери
Хотя принятый ответ также является правильным, на мой взгляд, этот ответ важнее. Вероятно, лучшим ответом будет сочетание обоих.
UncaAlby