PHP Include всегда терпит неудачу

  • Apache HTTP Server 2.2.21 с VirtualHosts под SuExec
  • PHP 5.3.8 через fcgid
  • Арх Линукс 2011.08.19

Нахожусь в процессе перехода с виртуального хостинга на VPS. Код, который у меня работал нормально до переноса, но теперь не работает в этой строке:

require_once($_SERVER['DOCUMENT_ROOT'] . 'includes/content/header.php');

Журнал ошибок говорит:

Неустранимая ошибка PHP: require_once(): Не удалось открыть требуемый '/srv/www/hostname/public/includes/content/header.php' (include_path='.:/usr/share/pear') в /srv/www/hostname /public/index.php в строке 3

Я попробовал ту же строку без корневой части документа, с ./ и без нее и т. д., но безуспешно. Никакой разницы с require, include_once или include тоже нет. Тем не менее, я могу убедиться, что файл существует именно в этом месте, скопировав его из журнала ошибок и cd записав в него…

Но чтобы быть абсолютно уверенным, я проверил возвращаемые значения includes, а также file_exists — все они возвращают false. Тем не менее, все файлы отбираются пользователем/группой SuExec, и никакая комбинация разрешений не помогает (для каталогов или файлов); пробовал с 644 по 777. Что тут происходит?

Изменить:

  • Тот же результат с файлами в том же каталоге.
  • Журналы ошибок Apache и SuExec ничего не сообщают.
  • Безопасный режим отключен в php.ini.
  • dirname(__FILE__) и exec('pwd') возвращают то же самое, что и $_SERVER['DOCUMENT_ROOT'], но без завершающей косой черты.
  • fread, file_get_contents и realpath(dirname(__FILE__)) все возвращают false.
  • set_include_path() не действует.
  • Запуск require через php-cgi непосредственно из командной строки возвращает внутреннюю ошибку сервера, а include возвращает пустой вывод; запуск через php возвращает пустой вывод.

Вот моя конфигурация vhost:

<VirtualHost *:80>
    ServerAdmin [email protected]
    DocumentRoot "/srv/www/hostname/public/"
    ServerName hostname.com
    ServerAlias www.hostname.com
    SuexecUserGroup hostname hostname
    ErrorLog "/srv/www/hostname/logs/error.log"
    LogLevel debug
    CustomLog "/srv/www/hostname/logs/access.log" combined

    <Directory /srv/www/hostname/public>
        Order allow,deny
        Allow from all
    </Directory>

    # http://www.linode.com/forums/viewtopic.php?t=2982
    <IfModule !mod_php5.c>
    <IfModule !mod_php5_filter.c>
    <IfModule !mod_php5_hooks.c>
    <IfModule mod_actions.c>
    <IfModule mod_alias.c>
    <IfModule mod_mime.c>
    <IfModule mod_fcgid.c>
        AddHandler php-fcgi .php
        Action php-fcgi /fcgid-bin/php-fcgid-wrapper
        Alias /fcgid-bin/ /srv/www/hostname/fcgid-bin/

        <Location /fcgid-bin/>
            SetHandler fcgid-script
            Options +ExecCGI
            Order allow,deny
            Allow from all
        </Location>

        ReWriteEngine On
        ReWriteRule ^/fcgid-bin/[^/]*$ / [PT]
    </IfModule>
    </IfModule>
    </IfModule>
    </IfModule>
    </IfModule>
    </IfModule>
    </IfModule>
</VirtualHost>

person Hugh Guiney    schedule 29.10.2011    source источник
comment
поскольку он использует функцию php 5.3, она УСТАРЕЛА в соответствии с: php.net/manual/ ru/features.safe-mode.php   -  person Kamil Lach    schedule 29.10.2011
comment
Я также убедился, что безопасный режим явно отключен в php.ini.   -  person Hugh Guiney    schedule 29.10.2011
comment
Можете ли вы проверить, какой пользователь запускает: fcgid   -  person Kamil Lach    schedule 29.10.2011
comment
Я нашел кое-что, что может помочь: webhostchat.co.uk/hosting-software-additional-add-products/   -  person Kamil Lach    schedule 29.10.2011
comment
Это пользователь SuExec, тот же пользователь, которому принадлежат все файлы и каталоги в docroot.   -  person Hugh Guiney    schedule 29.10.2011
comment
Эта ссылка просто говорит отключить безопасный режим, что и есть.   -  person Hugh Guiney    schedule 29.10.2011
comment
Скорее всего неправильно настроен сервер или отключены разрешения. Вы также можете попробовать вызвать fread или file_get_contents и посмотреть, что он возвращает. Если он возвращает ту же ошибку разрешений, то это 100% проблема с сервером.   -  person Steven    schedule 29.10.2011
comment
Я уже пробовал все возможные разрешения, как указано в OP. fread и file_get_contents оба возвращают false.   -  person Hugh Guiney    schedule 29.10.2011


Ответы (5)


Сначала убедитесь, что файл существует...

  • Затем попробуйте перейти к нему, используя www.hostname/public/includes/content/header.php (если вы используете что-то локальное, это будет localhost/public/includes/content/header.php)
  • Если это не загружается, либо что-то не так с вашей установкой, либо ваш файл поврежден.
  • Попробуйте загрузить заголовок из другого места
person blazingkin    schedule 29.10.2011
comment
включенные файлы не должны быть видны браузеру, как вы говорите. - person Kamil Lach; 29.10.2011

Вы проверяли права доступа к папкам, содержащим эти файлы?

Папка должна иметь разрешение на чтение для apache (или любого пользователя, который запускает http-сервер).

Вы пытались добавить путь, чтобы включить путь?

$path = '/includes/content';
set_include_path(get_include_path() . PATH_SEPARATOR . $path);

http://php.net/manual/en/function.set-include-path.php

person Kamil Lach    schedule 29.10.2011
comment
Права доступа к папке в порядке. set_include_path не действует. - person Hugh Guiney; 29.10.2011
comment
Проблема с конфигурацией не в вашем коде. Можете ли вы проверить файл .htaccess на наличие директивы AddHandler? - person Kamil Lach; 29.10.2011
comment
У меня нет .htaccess. Я добавил свою конфигурацию vhost в OP. - person Hugh Guiney; 29.10.2011

У меня всегда работает ->

if ( DIRECTORY_SEPARATOR == '/' )
{
    $path = dirname(__FILE__).'/';
}
else
{
    $path = str_replace('\\', '/', dirname(__FILE__)).'/';
}

попробуй!

[ОТРЕДАКТИРОВАНО]

использование функции dirname() работает всегда! $path = dirname(__FILE__).'/'; возможно проблема в вашем сервере. Не в программировании (сценарии).

person devasia2112    schedule 29.10.2011
comment
Уже исключены косые черты/отсутствие их; Кроме того, это Linux, поэтому разделителем всегда будет косая черта. Пожалуйста, прочитайте ОП. - person Hugh Guiney; 29.10.2011

DerfK в ServerFault понял: это было ограничение open_basedir.

person Hugh Guiney    schedule 30.10.2011

Возвращаясь к публикации решения:

Я не знал, что на open_basedir не повлияло отключение безопасного режима — он искал в /srv/http/, но не в /srv/www/, который будет содержать каталог для /srv/www/hostname/public/includes/content/.

person Hugh Guiney    schedule 15.12.2011