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.