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


345

Я намагаюся зрозуміти різницю між shell_exec()і exec()...

Я завжди використовував exec()для виконання серверних команд, коли б це використовувати shell_exec()?

Це shell_exec()лише скорочення exec()? Здається, це те саме, що має менші параметри.


2
хороший приклад , щоб побачити відмінність, щоб спробувати ці команди: date, whoami, ifconfig, netstat.

Є й інші функції: system (), passthru () ... див. Це пов'язане питання , і зокрема цю відповідь .
Гра "Подвійний"

1
Можливий дублікат PHP exec () vs system () vs passthru ()
1818

Відповіді:


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останній рядок виявляється порожнім.


що трапиться, якщо з командою виникає одна помилка? Я отримую помилку / Немає такого файлу чи каталогу, але як я можу зафіксувати його до змінної ????
Happy Coder

@AlwinAugustin: Так? Може бути написано в STDERR. Спробуйте додати 2>&1до кінця вашої команди, щоб перенаправити STDERR на STDOUT, якщо ви працюєте на машині Linux.
mpen

Я також додав його. Але все одно я отримую 0 як значення. Я використав одну команду wc -l, і якщо файлу немає, мені потрібно отримати повідомлення про помилку із записом Ні такого файлу чи каталогу.
Happy Coder

50

shell_exec- Виконати команду через оболонку і повернути повний вихід у вигляді рядка

exec - Виконати зовнішню програму.

Різниця полягає в тому, що при shell_execотриманні ви отримуєте вихідний показник.


4
Приємний короткий підсумок! Ще слід зазначити, що execповертає останній рядок виводу. При бажанні ви можете необов'язково передавати масив як другий параметр для захоплення повного виводу, а ціле число як третій параметр, щоб захопити повернене значення команди оболонки, яке можна використовувати для перевірки помилок. Найбільшим недоліком shell_execє те, що він повертає null, якщо команда не працює АБО, якщо вона не дає жодного результату, тому її повернене значення не може надійно використовуватися для перевірки помилок.
Шон Бін

38

Кілька відмінностей, які тут не торкалися:

  • За допомогою exec () ви можете передавати необов'язкові параметри змінної, які отримають масив вихідних рядків. У деяких випадках це може заощадити час, особливо якщо результат команд вже є табличним.

Порівняйте:

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.