Диагностика ошибок запуска PHP: от выявления причины до решения
Основные причины ошибок запуска PHP и их устранение
Наиболее эффективное решение: комплексная диагностика конфигурации PHP.
При ошибках запуска PHP (startup) первым делом необходимо определить, какой файл php.ini загружается, и проверить его синтаксис. Выполните в терминале:
php -i | grep 'Loaded Configuration File'Error php startup (ошибка запуска php)
Loaded Configuration File => /etc/php/8.2/cli/php.ini
Если php.ini не найден (None), PHP использует встроенные значения по умолчанию. В таком случае следует создать или указать корректный конфигурационный файл.
Затем проверьте наличие синтаксических ошибок в ini-файле. PHP не предоставляет встроенной утилиты для синтаксической проверки ini, но можно запустить PHP и перенаправить stderr:
php -v 2>&1
Если в выводе присутствуют строки PHP Warning: PHP Startup: или PHP Fatal error:, это указывает на проблемы при загрузке расширений, неверные директивы или конфликты.
Типичная ошибка: PHP Warning: PHP Startup: Unable to load dynamic library 'curl.so'
Причина: отсутствие файла расширения, неверный путь в extension_dir или несоответствие версии PHP (thread safety, API). Решение: проверьте директорию расширений командой php -i | grep extension_dir и убедитесь, что в ней присутствует нужный файл (например, curl.so). Для Linux используйте php -m и проверьте, загружено ли расширение. Для Windows аналогично проверьте наличие php_curl.dll.
Исправление: отредактируйте php.ini, задав правильный путь к расширению или раскомментировав строку extension=curl (без пути, если extension_dir уже корректен). После изменений перезапустите веб-сервер или проверьте через CLI.
1. Как проверить и исправить путь к extension_dir?
Выполните:
php -i | grep extension_dir
extension_dir => /usr/lib/php/20200930 => /usr/lib/php/20200930
Убедитесь, что директория существует и доступна для чтения. Если она отсутствует, создайте её или измените значение в php.ini:extension_dir = "/usr/lib/php/20200930"
В некоторых системах (например, macOS с Homebrew) extension_dir может указывать на несуществующую папку. Используйте символическую ссылку или укажите правильный путь от версии PHP.
2. Что делать, если расширение не загружается из-за отсутствия системных зависимостей?
Расширение может требовать внешние библиотеки (например, libcurl для curl, libssl для openssl). Проверьте зависимости с помощью ldd (Linux) или otool -L (macOS):
ldd /usr/lib/php/20200930/curl.so
Если вывод содержит not found, установите соответствующий пакет (например, sudo apt install libcurl4).
3. Как устранить ошибку memory_limit при запуске?
Ошибка Fatal error: Out of memory может возникать на раннем этапе, если memory_limit слишком мал. Увеличьте его в php.ini:
memory_limit = 256M
Для веб-сервера может потребоваться изменение в пуле FPM (/etc/php/8.2/fpm/php.ini).
Если после увеличения лимита ошибка сохраняется, проверьте, не вызвана ли она бесконечной рекурсией или утечкой памяти в одном из расширений. Отключайте расширения по одному для изоляции.
4. Как решить проблему с open_basedir?
Директива open_basedir ограничивает доступ к файловой системе. Если расширение пытается открыть файл за пределами разрешённых путей, возникает ошибка. Просмотрите текущее значение:
php -i | grep open_basedir
Если ограничение чрезмерно строгое, добавьте нужные пути в php.ini:
open_basedir = "/var/www:/tmp:/usr/share/php"
Или временно отключите, закомментировав директиву.
5. Как исправить конфликт расширений?
Два расширения могут пытаться определить одну и ту же функцию или символ. Типичный симптом: PHP Warning: Module 'mbstring' already loaded. Проверьте, не подключается ли расширение дважды (в основном файле и через каталог conf.d). Откройте php.ini и удалите дублирующийся extension=.
Также конфликты могут возникать при использовании разных версий одной библиотеки (например, zlib). В таком случае обновите все расширения до совместимых версий.
6. Что делать, если используется неправильный php.ini для SAPI?
PHP может загружать разные php.ini для CLI, CGI, FPM. Убедитесь, что вы редактируете правильный файл. Проверьте через:
php -i | grep 'Configuration File' && php -i | grep 'Scan this dir'
Configuration File (php.ini) Path => /etc/php/8.2/cli Loaded Configuration File => /etc/php/8.2/cli/php.ini Scan this dir for additional .ini files => /etc/php/8.2/cli/conf.d
Для FPM может быть отдельный путь. Используйте опцию -c /path/to/php.ini при запуске скрипта, чтобы принудительно указать конфигурацию.
Расширенные примеры диагностики и исправления ошибок запуска PHP
Приведённые ниже примеры помогут глубже понять механизмы загрузки PHP и локализовать проблему.
Пример 1. Комплексный скрипт для проверки окружения
Создайте файл check.php:
<?php
// Скрипт выводит все ошибки запуска, которые видны в error_log
error_reporting(E_ALL);
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
// Список критических расширений
$extensions = ['curl', 'mbstring', 'pdo_mysql', 'openssl', 'json'];
foreach ($extensions as $ext) {
if (extension_loaded($ext)) {
echo "$ext: OK\n";
} else {
echo "$ext: NOT LOADED\n";
}
}
// Вывод загруженного php.ini и директории сканирования
phpinfo(INFO_GENERAL);
?>
curl: OK mbstring: OK pdo_mysql: NOT LOADED ... (далее phpinfo)
Если какое-то расширение не загружено, обратитесь к выводу phpinfo для проверки директив.
Пример 2. Проверка наличия всех ini-файлов и их синтаксиса (имитация)
Хотя PHP не проверяет синтаксис ini напрямую, можно написать скрипт, который загружает каждый файл и ловит ошибки:
<?php
$iniFiles = glob('/etc/php/8.2/*/php.ini') + glob('/etc/php/8.2/*/conf.d/*.ini');
foreach ($iniFiles as $file) {
// Пытаемся загрузить файл через функцию parse_ini_file
$loaded = @parse_ini_file($file, true);
if ($loaded === false) {
echo "Ошибка синтаксиса в файле: $file\n";
} else {
echo "$file загружен успешно\n";
}
}
?>
/etc/php/8.2/cli/php.ini загружен успешно /etc/php/8.2/cli/conf.d/10-opcache.ini загружен успешно ... (возможны ошибки при некорректном синтаксисе)
Обратите внимание: parse_ini_file не полностью эмулирует механизм PHP, но может выявить грубые ошибки (отсутствие закрывающих кавычек и т.п.).
Пример 3. Использование опции -c для загрузки альтернативного php.ini
Если основной конфиг повреждён, временно укажите запасной:
php -c /path/to/backup/php.ini -m
Вывод покажет список модулей, загруженных с альтернативной конфигурацией. Сравните с обычным запуском.
Пример 4. Логирование ошибок запуска в отдельный файл
Иногда ошибки startup не видны на экране. Настройте запись в error_log в php.ini:
error_log = /var/log/php_startup_errors.log
display_errors = Off
display_startup_errors = Off
Затем выполните команду:
php -r '' 2>&1 | tee -a /var/log/php_startup_errors.log
Просмотрите лог после каждой попытки исправления.
Пример 5. Имитация ошибки загрузки расширения и её исправление
Создайте временное расширение-пустышку для теста (только для демонстрации). На практике достаточно использовать любое несуществующее имя:
# Добавьте в php.ini:
extension=nonexistent.so
PHP Warning: PHP Startup: Unable to load dynamic library 'nonexistent.so' (tried: /usr/lib/php/20200930/nonexistent.so (lib nonexistent)...) in Unknown on line 0
Отключите или исправьте строку, заменив на корректное имя.
Пример 6. Настройка include_path для уменьшения ошибок startup
Неверный include_path не вызывает ошибки startup напрямую, но может затруднить загрузку пользовательских скриптов. Проверьте:
php -i | grep include_path
include_path => .:/usr/share/php
Если нужно добавить каталог с пользовательскими библиотеками, отредактируйте php.ini:
include_path = ".:/usr/share/php:/home/user/my_libs"
Пример 7. Обработка множественных файлов конфигурации с помощью PHP_INI_SCAN_DIR
Переменная окружения PHP_INI_SCAN_DIR позволяет переопределить каталог сканирования дополнительных ini-файлов:
PHP_INI_SCAN_DIR=/custom/conf.d php -i
Это удобно для изолированного тестирования.
Пример 8. Устранение ошибки "undefined symbol" при загрузке расширения
Такая ошибка обычно возникает из-за несоответствия версий PHP или отсутствия общего символа. Например:
PHP Warning: PHP Startup: Unable to load dynamic library 'http.so' (tried: /usr/lib/php/20200930/http.so (/usr/lib/php/20200930/http.so: undefined symbol: php_http_params))
Решение: перекомпилируйте расширение для текущей версии PHP или установите версию из репозитория, совпадающую с установленной. На Ubuntu используйте pecl с указанием версии API:
sudo pecl install -f http