var_dump(realpath_cache_size(),realpath_cache_get());
int(0); array(0) {}
Ещё больше удивило, что этот баг до сих пор не решён в последних версиях PHP 5.6, а в документации про него ни слова (один комментарий пользователя месяц назад).
Некоторым гуглением было найдено решение: расширение, совмещающее в себе open_basedir и работающее через кеш путей php. Turbo_realpath.
В Pecl его нет, поэтому скачиваем архив с офсайта (для версий 5.4+, ниже смотрите на офсайте).
Установка в консоли:
unzip realpath_turbo_1.2.zip
cd realpath_turbo
phpize
./configure
make
make install
В php.ini или как, например, у меня в debian-like, для отдельного расширения своя конфигурация:
extension=turbo_realpath.so
заменяем настройки open_basedir
# clear all open_basedir restrictions
open_basedir=""
# replace it with
realpath_cache_basedir = /var/www/html/drupal
Расширение может ещё некоторые security улучшения:
; set this to 1 in order to disable dangerous PHP functions (link,symlink), or set to 0 in order to ignore potential security issues
<video></video>; установка в 1 чтобы отключить опасные PHP функции (link,symlink), или в 0 чтобы проигнорировать потенциально опасные вещи
realpath_cache_security = 1
; if you want, you can enable safe_mode, in order to do so, you have to switch off
; standard open_basedir setting...
; если хотите, можете включить safe_mode, в свою очередь, вы должны отключить стандартный open_basedir
open_basedir = off
; and then switch on custom realpath_cache_open_basedir setting,
; (remember, safe mode is not required by realpath_turbo extension,
; you can safely ignore these settings if you want)
; и тогда включить кастомный realpath_cache_open_basedir
; (помните, safe mode не требуется для расширения realpath_turbo, вы можете спокойно игнорировать эту опцию, если хотите)
real_path_cache_safe_mode = on
Комментарии (14)
nitso
08.11.2015 23:19+2Странное чувство не покидает меня после прочтения этой статьи.
Баг относится во-первых еще к версии 5.2, а во-вторых к включенному режиму safe_mode. Safe_mode выпилили еще пару лет назад (в 5.4 [раз] [два]). А вы рассказываете про решение этого бага в 5.6. Каша какая-то.b1rdex
09.11.2015 04:20+1Если задан open_basedir, то кэш тоже не работает. Насколько я понял, автору необходима эта настройка + кэш путей.
nitso
09.11.2015 11:57Меня смущает только то, что во всех найденых упоминаниях этого бага присутствует safe_mode. А основной задачей указанного в статье модуля является возвращение safe_mode в последние версии php: «This version adds support for safe_mode = on setting.»
romy4
09.11.2015 12:14Нет, задача стояла убрать постоянные обращения lstat в проверке путей мимо кеша realpath_cache. То, что он может включать safe_mode — это уже побочные фичи. Главное, что свою задачу он решает. В багрепорте Safe_mode упоминается лишь потому, что он оказывает такое же влияние на realpath_cache, как и open_basedir.
nitso
09.11.2015 13:25Перепроверил еще раз — при включенной опции open_basedir
realpath_cache_size()
действительно возвращает ноль. Не могу никак найти обработку open_basedir в контексте realpath_cache в исходниках.
Однако, если вы говорите о lstat как о функции PHP, а не о системном вызовеПо выводуrealpath_cache_size()
нельзя делать выводы о кэшеlstat()
(иstat()
), потому как для них реализованы два разных механима кэширования (в исходнике clearstatcache видно более наглядно). Вызов lstat() и без open_basedir не помещает значений в кэш realpath. Короткий тест на корректное функционирование кэша lstat:
<?php // обновляем mtime временного файла текущей датой touch("./tmp"); var_dump(lstat("./tmp")["mtime"]); // обновляем mtime "задним числом" touch("./tmp", 1347062644); var_dump(lstat("./tmp")["mtime"]); // очищаем кэш и проверяем результат clearstatcache(); var_dump(lstat("./tmp")["mtime"]);
$ php test.php int(1447062787) int(1447062787) int(1347062644)
$ php -dopen_basedir="." test.php int(1447062797) int(1447062797) int(1347062644)
FractalizeR
09.11.2015 10:50Кстати, вот тут есть объяснение, почему это до сих пор не «пофиксили».
romy4
09.11.2015 12:19+1Если честно, то странное объяснение. Open_basedir не даёт 100% гарантии, что юзер не откроет каким-то способом файл за пределами ограничений open_basedir. Остаётся вопрос, зачем вы тогда вообще сделали такую опцию? В общем, внятного ответа, почему не хотят исправить баг нет.
FractalizeR
09.11.2015 14:06Open_basedir не даёт 100% гарантии, что юзер не откроет каким-то способом файл за пределами ограничений open_basedir
Можно поподробнее? Что вы имеете ввиду?romy4
09.11.2015 15:09Только то, что написано по вашей ссылке в комментарии: «An open_basedir feature that doesn't actually guarantee that users can't open files outside of the specified base directory isn't useful.» Короче, я не очень понял Расмуса с его объяснением. Ну да, нельзя гарантировать, что файл не изменится, пока путь будет в кеше (это очевидно). Он типа не видит смысла в open_basedir, если каким-то образом решится аспект безопасности (наверное, про изменения вне кеша).
FractalizeR
09.11.2015 15:47Он имеет ввиду, что если сделать так, как предлагает этот реквест, то open_basedir перестанет иметь смысл, поскольку будет небезопасен.
turone
Ещё бы показательно было насколько помогло — была задержка такая то, теперь такая то, интересует эффективность расширения на вашем примере.
romy4
Вот на примере Друпала показательней всего, для чего так необходим realpath_cache. Плюс уменьшение cpu load и обращений к диску даже на небольших проектах, когда их много, в сумме даёт прирост производительности.