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


345

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

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

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


2
хороший пример , чтобы увидеть различие, чтобы попробовать эти команды: date, whoami, ifconfig, netstat.

Есть и другие функции: 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последняя строка оказывается пустой.


что произойдет, если с командой возникнет одна ошибка ..? Я получаю сообщение об ошибке / Нет такого файла или каталога, но как я могу записать его в переменную ????
— Счастливый кодер

@AlwinAugustin: А? Может быть, пишут в STDERR. Попробуйте добавить 2>&1в конец команды, чтобы перенаправить STDERR в STDOUT, если вы работаете на машине с Linux.
— mpen

Я добавил это также. Но все равно я получаю 0 в качестве значения. Я использовал одну команду wc -l, и если файла нет, мне нужно получить сообщение об ошибке, говорящее, что нет такого файла или каталога.
— Счастливый кодер

50

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

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

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


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.


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

Хотя принятый ответ также является правильным, на мой взгляд, этот ответ важнее. Вероятно, лучшим ответом будет сочетание обоих.
— UncaAlby
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.