PHP, когда я должен выполнить в оболочку, против внутренних функций PHP.Спектакль?Безопасность? - PullRequest
2 голосов
/ 26 ноября 2011

Я Linux SysAdmin и всегда работаю в Bash. Я очень опытный администратор PHP, но довольно плохо знаком с написанием PHP-скриптов.

По каким причинам я хотел бы получать выходные данные от системной команды, а не от внутренних функций PHP. Я предполагаю, что у вас есть проблемы с переносимостью, хотя в моем случае это не проблема.

Например, Я мог бы получить список каталогов с помощью ls и функцию стиля exec. или сделайте что-нибудь с opendir ('.') и циклом.

Каковы соображения производительности?

Вот что у меня сейчас,

<?php
// Directory Open
$myDirectory = opendir('/media/ARCHIVE/Documents/conf/web_confs');

// Array of Elements
while($entryName = readdir($myDirectory)) {
$dirArray[] = $entryName;
}
// Directory Close
closedir($myDirectory);

// Sort Array
sort($dirArray);
?>

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

это системный код, который не будет вводить какой-либо тип ввода. Даже из URL. Кроме того, среда является крупномасштабной, и все системы настроены на производительность и часто профилируются.

То, что я делаю это наилучшим способом, - это то, что я ищу. Я действительно был бы признателен за любой вклад, так как мой опыт несколько ограничен.

Ответы [ 6 ]

3 голосов
/ 26 ноября 2011

Для этого конкретного случая есть scandir (http://www.php.net/manual/en/function.scandir.php),, который я бы использовал.

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

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

2 голосов
/ 26 ноября 2011

Для вашего примера чтения каталога выполнение в PHP, безусловно, будет быстрее, чем процесс загрузки ОС.

Что касается безопасности: встроенные функции PHP будут иметь меньше проблем с безопасностью, чемзапуск процесса через оболочку.(Например, функция PHP system.) Запуск оболочки является особенно рискованным делом, если вы используете пользовательский ввод в команду для оболочки: вы должны убедиться, что независимо от того, что пользователь может ввести, вы будете знать, что такое команда оболочкиВы построите, будет делать!(Это похоже на SQL-инъекцию, если вы знакомы с этим.) PHP предоставляет функции для этого, и страницы справочника для system и exec отмечают их.

Тем не менее, чтение каталога с использованиемввод пользователя также имеет соображения безопасности (в общем случае).Всегда убедитесь, что вы дезинфицируете ввод пользователя в соответствии с вашим делом.Если они могут читать любой каталог, opendir($the_users_input), вероятно, в порядке.Если они могут читать что-либо только в /foo/bar, то вам, вероятно, нужно убедиться, что они не пропускают вас ../../etc/passwd.

1 голос
/ 26 ноября 2011

Выполнение команды bash обычно будет медленнее.
В двух ситуациях вам может потребоваться вызов внешней команды bash

  1. Когда PHP не поддерживает встроенные библиотеки (или требует установки пакета PECL). Такие как rsync, wget, seige, mysqldump, ab (бенчмарк apache). Это время, вы найдете, что выполнить внешнюю команду проще

  2. Скрипт bash может получить лучший результат, чем встроенная функция PHP, как, например, в вашем примере. Или другой пример: - du -h $dir | sort -nr.

Как уже указывают остальные, если производительность вызывает беспокойство, сделайте тест и сравните себя.
Если вас беспокоит безопасность, выполнение внешней команды bash сопряжено с большим риском.


Если сканирование действительно является горлышком бутылки,
вам следует рассмотреть возможность кэширования в хранилище, обеспечивающее быстрый доступ, например, APC, memcache.

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

Пример

if ( cache_found())
{
  // return results from cache
}
else
{
  // scan dir
  // set the scan result into cache
  // return scan result;
}

С помощью этой типичной техники попадания или промаха ваша производительность может значительно улучшиться.

1 голос
/ 26 ноября 2011

Я бы не сказал, что функции PHP медленнее, поскольку они в основном отображаются на базовые функции библиотеки C.Разумеется, пользовательские исполняемые файлы - это отдельная история.

Использование exec означает создание процесса с копированием всей памяти процесса (я знаю, что здесь пропущен vfork) и заменой памяти процесса новым исполняемым файлом.Последнее на самом деле довольно быстро.Я бы сказал, что обычная система C2D может обрабатывать несколько тысяч exec в секунду.

0 голосов
/ 11 июля 2015

TechZilla - похоже, у вас и YCS есть недоразумение.Я бы проигнорировал это.

У меня есть 2, надеюсь, полезных ввода:

1.Моя самая надежная догадка - придерживаться вызовов PHP, а не отбрасывать другой процесс :


Формирование нового процесса делает все виды забавных вещей: дескриптор файла и копии состояния, резервное копирование всегостек, резервное копирование состояния регистра, перемещение областей памяти, загрузка нового исполняемого файла с диска, загрузка каждой из его общих библиотек, которые еще не загружены, скачки инструкций и регистров данных буквально тысячи раз (что означает много вероятных ЦПкэш-память отсутствует!) для исправления местоположения памяти огромная головная боль .


Вызов функции (даже для привязки C) - это всего лишь немного дополнительного пространства в стеке инесколько прыжков указателя инструкций.В самый первый раз, когда ваше приложение загружается, оно будет иметь дело с загрузкой любых зависимых библиотек (головная боль определена выше), но они остаются в памяти.Не так много, как большое дело.Вы не можете сделать то же самое с целой программой.

2.Предложение memcache от Ajreal звучит как хорошее третье решение

Вы всегда можете использовать inotify, чтобы сообщить сценарию, когда важный каталог был изменен, и коснуться (не обязательно сенсорный инструмент) db (даже плоский файл).или memcache), сообщая, что оно было изменено.

Весь код, проверяющий содержимое каталога, может проверять кэш, если не указано иное.Кэш файловой системы Linux сделает проверку вашего файла мьютекса очень эффективной: только память, без попадания на диск, если он не был изменен.

0 голосов
/ 26 ноября 2011

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

Вы назвали их сами - вы знакомы с ними.
Этого достаточно

С точки зрения производительности это не имеет значения.

Посмотрите, вы задумываетесь о самой маленькой части системы.
Чтобы обработать запрос пользователя, веб-сервер сделает сотнитакие дисковые поиски.Почему их не волнует?Но вы хотите, чтобы super-duper-extra-micro оптимизировал только этот.
И вы даже не знаете, требуется это или нет.
В этом нет логики.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...