Мониторинг и анализ логов PHP

Раздел: Администрирование -> Логирование

Основные способы просмотра журнала PHP

Как отслеживать новые записи в логах PHP в реальном времени?

Для непрерывного мониторинга активно дополняемого файла tail -f остаётся самым надёжным инструментом. Команда выводит последние строки файла и затем отображает каждую новую строку по мере её записи.

tail -f /var/log/php_errors.log

Journal php view (просмотр журнала php)

Если лог-файл расположен в другом месте, путь можно уточнить через phpinfo() или конфигурацию php.ini (директивы error_log). Для фильтрации конкретного типа ошибок добавляется grep:

tail -f /var/log/php_errors.log | grep --line-buffered "PHP Fatal error"

Возможные проблемы:

  • Permission denied - решение: выполнять команду под пользователем, которому разрешён доступ к файлу, или изменить права (например, sudo tail -f ...).
  • Файл отсутствует - убедиться, что PHP действительно пишет ошибки в лог; проверить настройку log_errors = On в php.ini.
  • Ротация логов - если файл пересоздаётся (logrotate), tail -f может перестать отслеживать новый файл. Помогает опция --follow=name --retry.

Цель использования: оперативное выявление ошибок в работающем приложении, особенно полезно при отладке и разборе инцидентов.

Как просматривать большие файлы логов PHP без перегрузки памяти?

Когда объём логов достигает гигабайтов, открывать их в текстовом редакторе нерационально. Утилита less загружает только видимую часть файла и позволяет быстро перемещаться.

less /var/log/php_fpm.log

Внутри less работают следующие сочетания: G - конец файла, gg - начало, /pattern - поиск, N - следующий результат. Для просмотра свежих строк в реальном времени (как tail -f) внутри less нажимается F.

Типичные ошибки:

  • Отсутствие цветового выделения - можно включить подсветку синтаксиса, передав опцию -R (less -R).
  • Неверное завершение - выход из режима слежения (F) по Ctrl+C.

Цель: анализ архивных логов, поиск редких ошибок в больших объёмах данных.

Как просматривать логи PHP-FPM через systemd?

Если PHP-FPM управляется systemd, его вывод направляется в системный журнал. Доступ к нему осуществляется через journalctl.

# просмотр последних 50 записей для юнита php-fpm
journalctl -u php-fpm -n 50

# слежение за новыми записями
journalctl -u php-fpm -f

# фильтр по временному диапазону
journalctl -u php-fpm --since "10 minutes ago"

Дополнительно можно указать -o json-pretty для структурированного вывода.

Проблемы:

  • Требуются права root - использование sudo.
  • Смешивание с другими сообщениями - для исключения посторонних записей применяется -u с точным именем юнита.

Цель: унифицированный доступ к логам служб в дистрибутивах с systemd (CentOS 7+, Ubuntu 16.04+).

Как организовать просмотр логов PHP через веб-интерфейс?

Силами самого PHP можно создать простую страницу для чтения и отображения логов. Это удобно для удалённого администрирования без доступа к SSH.

// log_viewer.php
$logFile = '/var/log/php_errors.log';
$lines = 100;
if (file_exists($logFile)) {
    $file = new SplFileObject($logFile, 'r');
    $file->seek(PHP_INT_MAX);
    $totalLines = $file->key();
    $startLine = max(0, $totalLines - $lines);
    foreach (new LimitIterator($file, $startLine, $lines) as $line) {
        echo htmlspecialchars($line) . "<br>";
    }
}

Для безопасности доступ к скрипту следует ограничить паролем (HTTP Basic Auth) или IP-адресом через директиву Allow.

Возможные ошибки:

  • Отказ в чтении файла - у пользователя веб-сервера должны быть права на чтение лога.
  • Проблемы с производительностью - при больших файлах seek может быть медленным; рекомендуется читать только конец файла через fread с отступом от конца.

Цель: быстрый просмотр логов из браузера для команд без прямого доступа к серверу.

Как быстро получить статистику по ошибкам в логах PHP?

Командные утилиты awk и sed позволяют сгруппировать записи по типу ошибки и подсчитать частоту.

# подсчёт вхождений разных уровней ошибок (Notice, Warning, Fatal)
awk '{for(i=1;i<=NF;i++) if($i~/PHP (Notice|Warning|Fatal|Parse)/) count[$i]++} END {for(t in count) print t, count[t]}' /var/log/php_errors.log

Результат выводится в виде пар “тип количество”. Аналогично можно выделить самые частые сообщения.

Сложности:

  • Нестандартный формат лога - если PHP настроен на другой формат (Syslog), регулярные выражения придётся адаптировать.

Цель: оценка стабильности приложения, выявление повторяющихся ошибок.

Расширенные примеры просмотра и анализа логов PHP

Ниже приведены нестандартные техники работы с журналами PHP, включающие скриптовую автоматизацию и асинхронную обработку.

Пример 1: Скрипт на PHP с цветовой подсветкой ошибок и загрузкой последних строк

Следующий скрипт читает конец лога (последние 50 строк), выделяет критические ошибки красным, предупреждения жёлтым, остальные сообщения серым.

Пример
// color_highlight.php
$logFile = '/var/log/php_errors.log';
$lines = 50;
$handle = fopen($logFile, 'r');
if ($handle) {
    fseek($handle, -max(1, filesize($logFile) * 0.1), SEEK_END); // смещение
    $buffer = stream_get_contents($handle);
    fclose($handle);
    $allLines = explode("\n", $buffer);
    $lastLines = array_slice($allLines, -$lines);
    foreach ($lastLines as $line) {
        if (preg_match('/PHP Fatal error|PHP Catchable fatal error/i', $line)) {
            $color = 'red';
        } elseif (preg_match('/PHP Warning/i', $line)) {
            $color = 'orange';
        } else {
            $color = 'gray';
        }
        echo "<span style='color: $color'>" . htmlspecialchars($line) . "</span><br>";
    }
}

Результат: на веб-странице отображаются последние записи с цветовой индикацией серьёзности.

[25-Nov-2024 10:23:45 UTC] PHP Fatal error:  Uncaught TypeError: ...
[25-Nov-2024 10:23:44 UTC] PHP Warning:  Undefined array key ...

Пример 2: Асинхронный мониторинг с ReactPHP

Использование библиотеки ReactPHP для неблокирующего чтения лога в реальном времени. Скрипт запускается из командной строки и выводит каждую новую строку с меткой времени.

Пример
// async_tail.php
require 'vendor/autoload.php';
use React\EventLoop\Factory;
use React\Stream\ReadableResourceStream;

$loop = Factory::create();
$stream = fopen('/var/log/php_errors.log', 'r');
fseek($stream, 0, SEEK_END); // начинаем с конца
$readable = new ReadableResourceStream($stream, $loop);
$readable->on('data', function ($chunk) {
    echo '[' . date('H:i:s') . '] ' . $chunk;
});
$loop->run();

После запуска скрипта каждая новая запись в логе немедленно выводится в консоль. Это аналог tail -f, реализованный на PHP.

[11:05:32] [25-Nov-2024 11:05:32 UTC] PHP Notice: Undefined variable: x
[11:05:33] [25-Nov-2024 11:05:33 UTC] PHP Stack trace: ...

Пример 3: Объединение логов из нескольких файлов с помощью multitail

Утилита multitail позволяет отображать несколько лог-файлов одновременно в одном окне терминала. Установка: apt install multitail.

Пример
multitail /var/log/php_errors.log /var/log/php-fpm.log /var/log/nginx/error.log

Каждому файлу выделяется собственная панель с цветом. Переключение между панелями - клавиша b. Можно фильтровать строки по ключевым словам прямо в процессе просмотра.

Результат: на экране терминала одновременно обновляются три лога.

+-----[ /var/log/php_errors.log ]----------------------+
| PHP Fatal error: ...                                   |
| PHP Warning: ...                                       |
+-----[ /var/log/php-fpm.log ]-------------------------+
| WARNING: [pool www] server reached pm.max_children...  |
+-----[ /var/log/nginx/error.log ]--------------------+
| 2024/11/25 11:00:00 [error] ...                       |

Пример 4: Анализ логов PHP с помощью Logstash и Elasticsearch (централизованное логирование)

Для сложной инфраструктуры логи отправляются в Elasticsearch через Logstash. Пример конфигурации Logstash для парсинга стандартного PHP-лога.

Пример
# logstash.conf
input {
  file {
    path => "/var/log/php_errors.log"
    start_position => "beginning"
    sincedb_path => "/dev/null"
  }
}
filter {
  grok {
    match => { "message" => "%{TIMESTAMP_ISO8601:timestamp} %{GREEDYDATA:message}" }
  }
}
output {
  elasticsearch {
    hosts => ["localhost:9200"]
    index => "php-logs-%{+YYYY.MM.dd}"
  }
}

После запуска Logstash логи индексируются, и в Kibana можно строить дашборды с графиками ошибок, фильтрацией по временным интервалам и полям.

Результат: централизованное хранение и визуализация логов. Пример запроса в Kibana: message: "Fatal error".

Пример 5: Использование inotifywait для реакции на изменения в логе

Утилита inotifywait отслеживает изменения файловой системы. С её помощью можно запускать произвольный скрипт при каждой новой записи в лог PHP.

Пример
#!/bin/bash
inotifywait -m -e modify /var/log/php_errors.log |
while read file event; do
    tail -n1 /var/log/php_errors.log >> /tmp/php_last_error.log
    # дополнительно: отправить уведомление через Telegram
    curl -s -X POST https://api.telegram.org/botTOKEN/sendMessage -d chat_id=ID -d text="Новая ошибка"
done

Скрипт работает в фоне, копирует последнюю строку в отдельный файл и уведомляет администратора. Проблема: при высокой частоте записей возможна потеря сообщений. Решение - использовать буфер с отметками времени.

Пример 6: Частичное восстановление повреждённого лога с помощью strings

Если файл лога повреждён (бинарный мусор), утилита strings извлекает все читаемые строки.

Пример
strings /var/log/php_errors.log | grep -i "error" | head -30

Выводятся только те фрагменты, которые содержат подстроку “error”. Это может помочь выявить текстовые сообщения среди двоичного шума.

Просмотр журнала PHP - comments

En
Journal php view (php)