PHP exec () против system () против passthru ()

312

В чем различия?

Есть ли конкретная ситуация или причина для каждой функции? Если да, можете ли вы привести примеры таких ситуаций?

PHP.net говорит, что они используются для выполнения внешних программ. см. ссылку. Из примеров, которые я вижу, я не вижу никакой очевидной разницы.

Если бы я просто запустил скрипт (bash или python), какую функцию вы бы порекомендовали мне использовать?

codingbear
источник
16
Есть также proc_open()и то popen(), и другое, что позволяет более высокую степень контроля над порожденным процессом.
Кристиан

Ответы:

195

У них немного разные цели.

  • exec() предназначен для вызова системной команды и, возможно, работы с выводом самостоятельно.
  • system() предназначен для выполнения системной команды и немедленного отображения выходных данных - предположительно, текста.
  • passthru() предназначен для выполнения системной команды, от которой вы хотите получить сырой возврат - предположительно что-то двоичное.

Несмотря на это, я предлагаю вам не использовать ни один из них. Все они производят крайне непереносимый код.

Калий
источник
147
Иногда переносимость приходится приносить в жертву функциональности. Есть некоторые вещи, которые PHP просто не может сделать хорошо.
Фрэнк Крук
30
@Kalium: не могли бы вы подробнее рассказать о своем заявлении? просто указание какой-то расплывчатой ​​процентной статистики меня не убеждает. Я считаю, что использовать системные вызовы для выполнения сценариев вполне нормально, пока все приложение не зависит от одной группы сценариев в бэкэнде.
codingbear
46
@Christian izkata@izein:~$ dir -bash: dir: command not found- FreeBSD
Изката
5
@OZ_ Я попал в ситуацию, когда мне пришлось делать очень дорогие вычисления. Для этого не было доступно ни одного PHP-модуля. Я написал свою собственную программу на C и вызываю ее с помощью passthru (). Иногда портативность может быть менее важной, чем другие вещи. Зависит от проекта.
Паоло
9
Кроме того , это заблуждение думать , что PHP является переносимым до тех пор , как вы избежать exec, system, passthru. PHP-код зависит от среды, в которой он работает, и многие ошибки безопасности связаны с тем, что это не учитывается. Вот быстрый пример: stackoverflow.com/questions/3003145/…
Pacerier
131

Как взято из http://php.net/ && Chipmunkninja :

Система () Функция

Системная функция в PHP принимает строковый аргумент с командой для выполнения, а также любые аргументы, которые вы хотите передать этой команде. Эта функция выполняет указанную команду и выводит любой результирующий текст в выходной поток (либо вывод HTTP в ситуации веб-сервера, либо консоль, если вы используете PHP в качестве инструмента командной строки). Возвращение этой функции - последняя строка вывода программы, если она генерирует текстовый вывод.

Exec () Функция

Системная функция довольно полезна и мощна, но одной из самых больших проблем является то, что весь полученный в результате текст из программы направляется непосредственно в выходной поток. Будут ситуации, когда вы захотите отформатировать полученный текст и отобразить его каким-либо другим способом или не отобразить его вообще.

Для этого отлично работает функция exec в PHP. Вместо того, чтобы автоматически выгружать весь текст, сгенерированный исполняемой программой, в выходной поток, он дает вам возможность поместить этот текст в массив, возвращенный во втором параметре функции:

Shell_exec () Функция

Большинство программ, которые мы выполняли до настоящего времени, были более или менее реальными программами1. Однако среда, в которой работают пользователи Windows и Unix, на самом деле намного богаче, чем эта. Пользователи Windows могут использовать программу командной строки Windows, cmd.exe. Эта программа называется командной оболочкой.

PassThru () Функция

Одна захватывающая функция, которую предоставляет PHP, похожая на те, что мы видели до сих пор, это функция passthru. Эта функция, как и другие, выполняет программу, которую вы ей сообщаете. Однако затем он немедленно отправляет необработанный вывод из этой программы в поток вывода, с которым в данный момент работает PHP (т. Е. Либо HTTP в сценарии веб-сервера, либо оболочка в версии PHP командной строки).

Proc_open () Функция и POPEN () функция

proc_open () похож на popen (), но обеспечивает гораздо большую степень контроля над выполнением программы. cmd - это команда, которая должна быть выполнена оболочкой. descriptorspec - это индексированный массив, где ключ представляет номер дескриптора, а значение представляет, как PHP передает этот дескриптор дочернему процессу. каналы будут установлены в индексированный массив файловых указателей, которые соответствуют концу PHP всех созданных каналов. Возвращаемое значение является ресурсом, представляющим процесс; Вы должны освободить его с помощью proc_close (), когда закончите с ним.

Динеш Саини
источник
6
Скорость выполнения shell_exec выше, чем у других альтернатив.
Динеш Саини
29
Вы должны упомянуть, что вы скопировали свой ответ непосредственно из ChipmunkNinja .
TachyonVortex
7
@TachyonVortex, к счастью, он дословно скопировал ответ, потому что ChipmunkNinja больше не существует.
Phileo99
2
Копия этой статьи есть на машине обратного хода: web.archive.org/web/20130809032648/http://chipmunkninja.com/…
bagonyi
2
Что насчет popen и proc_open?
CMCDragonkai
103

Предыдущие ответы кажутся немного запутанными или неполными, поэтому вот таблица различий ...

+----------------+-----------------+----------------+----------------+
|    Command     | Displays Output | Can Get Output | Gets Exit Code |
+----------------+-----------------+----------------+----------------+
| system()       | Yes (as text)   | Last line only | Yes            |
| passthru()     | Yes (raw)       | No             | Yes            |
| exec()         | No              | Yes (array)    | Yes            |
| shell_exec()   | No              | Yes (string)   | No             |
| backticks (``) | No              | Yes (string)   | No             |
+----------------+-----------------+----------------+----------------+
  • «Отображает вывод» означает, что он выводит выходные данные в браузер (или вывод из командной строки, если работает из командной строки).
  • «Can Get Output» означает, что вы можете получить выходные данные команды и назначить их переменной PHP.
  • «Код выхода» - это специальное значение, возвращаемое командой (также называемое «статусом возврата»). Ноль обычно означает, что он был успешным, другие значения обычно являются кодами ошибок.

Другие разные вещи, о которых нужно знать:

  • Shell_exec () и оператор backticks делают то же самое.
  • Есть также proc_open () и popen (), которые позволяют интерактивно читать / записывать потоки с помощью исполняемой команды.
  • Добавьте «2> & 1» в командную строку, если вы также хотите захватывать / отображать сообщения об ошибках.
  • Используйте escapeshellcmd () для экранирования аргументов команды, которые могут содержать проблемные символы.
  • Если передать переменную $ output в exec () для сохранения вывода, если $ output не пуст, он добавит новый вывод в него. Поэтому вам может понадобиться сначала сбросить ($ output).
orrd
источник
какие из них могут выполнить файл php?
Джонни, почему
1
@johnywhy нет по сути - если вы явно не вызываете php cli или что-то подобное. Я полагаю, вы хотите, includeи друзья
Хаген фон Айтцен
21

На самом деле все сводится к тому, как вы хотите обработать вывод, который может вернуть команда, и хотите ли вы, чтобы ваш PHP-скрипт ожидал завершения программы вызываемого абонента, или нет.

  • exec выполняет команду и передает вывод вызывающей стороне (или возвращает ее в необязательной переменной).

  • passthruпохож на exec()функцию в том, что он выполняет команду. Эта функция должна использоваться вместо exec()или system()когда выходные данные команды Unix представляют собой двоичные данные, которые необходимо передавать непосредственно обратно в браузер.

  • system выполняет внешнюю программу и отображает вывод, но только последнюю строку.

Если вам нужно выполнить команду и передать все данные из команды обратно без каких-либо помех, используйте passthru()функцию.

Коди Коулан
источник
8

Если вы запускаете свой PHP-скрипт из командной строки, passthru()есть одно большое преимущество. Это позволит вам выполнять скрипты / программы, такие как vim, dialogи т. Д., Позволяя этим программам управлять и возвращаться к вашему сценарию только после завершения.

Если вы используете system()или exec()для выполнения этих скриптов / программ, это просто не будет работать.

Понял: По какой - то причине, вы не можете выполнить lessс passthru()в PHP.

Matt
источник
1
Я не понимаю, что вы говорите. Вы можете выполнять программы как из CLI, так и (F) CGI (а также из mod_php). Могут быть системные ограничения, такие как selinux. Но хорошо настроенная система отключит их выборочно. Конечно, общий хостинг - это отдельная история, но вы не будете предлагать общую среду и уважаемым клиентам, нет?
Кристиан