PHP lstat полный путь много раз, прежде чем читать ищет файл. И это происходит, когда в конфигурации apache указан httpd PHP_ADMIN_VALUE open_basedir или если safe_mode включен.
Если у меня простой веб-сайт только со страницей phpinfo.php, а внутри у нас есть только "".
Предположим, у нас есть последняя версия httpd (2.2.15) и PHP (5.2.13 или 5.3.2).
Если мы укажем safe_mode = on или PHP_ADMIN_VALUE open_basedir в конфигурации виртуального хоста:
<Directory "/usr/local/myspace/webspace/httpdocs"> PHP_ADMIN_VALUE open_basedir "/usr/local/myspace/webspace" </Directory> <VirtualHost *:80> ServerName damorealt.xoom.it DocumentRoot "/usr/local/myspace/webspace/httpdocs" CustomLog /var/log/httpd/damorealt/access_log combined ErrorLog /var/log/httpd/damorealt/error_log </VirtualHost >
Страница вызова http://damorealt.xoom.it/phpinfo.php мы можем воспроизвести следующее поведение:
Первая проверка
25933 lstat("/usr", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 25933 lstat("/usr/local", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 25933 lstat("/usr/local/myspace", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 25933 lstat("/usr/local/myspace/webspace", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 25933 lstat("/usr/local/myspace/webspace/httpdocs", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 25933 lstat("/usr/local/myspace/webspace/httpdocs/phpinfo.php", {st_mode=S_IFREG|0644, st_size=16, ...}) = 0
Вторая проверка
25933 lstat("/usr", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 25933 lstat("/usr/local", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 25933 lstat("/usr/local/myspace", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 25933 lstat("/usr/local/myspace/webspace", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 25933 lstat("/usr/local/myspace/webspace/httpdocs", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 25933 lstat("/usr/local/myspace/webspace/httpdocs/phpinfo.php", {st_mode=S_IFREG|0644, st_size=16, ...}) = 0
Третья проверка (неполная)
25933 lstat("/usr", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 25933 lstat("/usr/local", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 25933 lstat("/usr/local/myspace", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 25933 lstat("/usr/local/myspace/webspace", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
Пятая проверка.
25933 lstat("/usr", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 25933 lstat("/usr/local", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 25933 lstat("/usr/local/myspace", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 25933 lstat("/usr/local/myspace/webspace", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 25933 lstat("/usr/local/myspace/webspace/httpdocs", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 25933 lstat("/usr/local/myspace/webspace/httpdocs/phpinfo.php", {st_mode=S_IFREG|0644, st_size=16, ...}) = 0
Прочтите файл!
25933 open("/usr/local/myspace/webspace/httpdocs/phpinfo.php", O_RDONLY) = 16 25933 fstat(16, {st_mode=S_IFREG|0644, st_size=16, ...}) = 0 25933 read(16, "\n", 8192) = 16 25933 read(16, "", 8192) = 0 25933 read(16, "", 8192) = 0 25933 close(16) = 0
Если PHP_ADMIN_VALUE open_basedir "/ usr / local / myspace / webspace" удален::
Первая проверка
26235 time(NULL) = 1278696735 26235 lstat("/usr", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 26235 lstat("/usr/local", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 26235 lstat("/usr/local/myspace", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 26235 lstat("/usr/local/myspace/webspace", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 26235 lstat("/usr/local/myspace/webspace/httpdocs", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 26235 lstat("/usr/local/myspace/webspace/httpdocs/phpinfo.php", {st_mode=S_IFREG|0644, st_size=16, ...}) = 0
Прочтите файл.
26235 open("/usr/local/myspace/webspace/httpdocs/phpinfo.php", O_RDONLY) = 16 26235 fstat(16, {st_mode=S_IFREG|0644, st_size=16, ...}) = 0 26235 read(16, "\n", 8192) = 16 26235 read(16, "", 8192) = 0 26235 read(16, "", 8192) = 0 26235 close(16) = 0 26235 uname({sys="Linux", node="svilpar4", ...}) = 0 26235 time(NULL) = 1278696735 26235 writev(15, [{"HTTP/1.1 200 OK\r\nDate: Fri, 09 J"..., 173},[...] 26235 chdir("/") = 0
Может ли кто-нибудь объяснить мне, почему у PHP такое поведение?
Кеш Realpath отключен, если установлены safe_mode или open_basedir. Это резко снижает производительность PHP Engine, и такое поведение может поставить сервер на колени. Тем более, что документации не хватает!
Взглянув на исходный код main / main.c движка PHP 5.2.13, вы увидите:
1292: /* Disable realpath cache if safe_mode or open_basedir are set */ if (PG(safe_mode) || (PG(open_basedir) && *PG(open_basedir))) { CWDG(realpath_cache_size_limit) = 0; } 1769: /* Disable realpath cache if safe_mode or open_basedir are set */ if (PG(safe_mode) || (PG(open_basedir) && *PG(open_basedir))) { CWDG(realpath_cache_size_limit) = 0; }
Пожалуйста, обратитесь к: http://bugs.php.net/bug.php?id=52312
обходное решение описано здесь: https://github.com/Whissi/realpath_turbo
с этим расширением вы можете использовать кеш realpatch с включенным openbasedir