LXF164: Мониторить систему
|
|
|
Учебник. Наблюдайте за тем, что происходит в Linux, с syslog-ng
Журналы: Следим за системой
Есть такое место, где Linux прячет свои самые глубокие и темные секреты. Нейл Ботвик бестрепетно заглядывает туда.
В вашей системе есть каталог, куда вы, возможно, никогда не заходили; но он жизненно необходим и очень полезен, если что-то разладится. Это /var/log; в нем есть файлы журналов (они же – лог-файлы) почти всех действий, происходящих в системе. Большую часть операций журналирования выполняет системный логгер. Это фоновый демон, управляющий записью в лог-файлы – что позволяет не писать в каждой программе свой код для ведения журналов: все они вызывают одни и те же системные функции. В Linux несколько таких логгеров; они делают почти одно и то же. Мы займемся syslog-ng, одним из самых популярных. Почти все сказанное будет верно для любого из них.
Зачем нужен системный логгер? Причину мы уже назвали: чтоб не дублировать код. Это также означает, что логгер может быть гораздо более гибким и мощным. Обычно он пишет все сообщения в один файл в каталоге /var/log (в случае с syslog-ng – файл messages). Но это не единственный вариант: сообщения можно отправлять в разные файлы по разным критериям, и даже перенаправлять другому логгеру на другой компьютер.
Обычная строка из лог-файла выглядит примерно так:
Aug 16 16:54:51 hactar smartd[3191]: Device: /dev/sdc [SAT],SMART Usage Attribute: 194 Temperature_Celsius changed from 101 to 100
Каждая запись в лог-файле – это одна строка, начинающаяся с даты и времени; затем следуют имя хоста и команда. В данном примере это команда smartd – демон, отслеживающий состояние жесткого диска, с идентификатором процесса 3191 (идентификатор указывается не для всех процессов, но для большинства). После имени процесса и идентификатора идет двоеточие, а за ним – само сообщение. Единого формата сообщений нет: это то, что программа отправляет логгеру. В этом примере smartd сообщает об изменении температуры одного из жестких дисков. Зная, что делает системный логгер, вы с его помощью сможете отслеживать происходящее в вашей системе. Одна из нередких ситуаций – посмотреть, что идет не так при попытке запуска программы или использования устройства. Команда tail показывает десять последних строк файла, но добавьте параметр --follow, и она будет показывать новые строки файла; таким образом, команда
tail --follow /var/log/messages
будет выводить новые сообщения по мере их записи в лог-файл. Системный лог-файл часто не имеет доступа на чтение для всех, и может понадобиться выполнить эту команду от имени суперпользователя-root или с префиксом sudo, иначе ничего не увидишь. Для просмотра, как это работает, запустите команду и вставьте флэшку. Вы увидите системные сообщения о том, что обнаружен USB-диск, идентифицирован как устройство хранения данных и прочитана его таблица разделов. Имя процесса в данном случае – kernel, так как горячее подключение устройств обрабатывается напрямую ядром. Так как в фоне выполняются и другие процессы, в вывод команды могут попасть сообщения от любого из них. Отфильтровать их можно с помощью grep. Команда
tail --follow /var/log/messages | grep kernel:
исключит все сообщения, в которых нет слова kernel: – завершающее: необходимо, чтобы выделить только сообщения от ядра.
Создаем фильтры
Помещать все сообщения в один файл – не всегда лучший вариант. Некоторые программы генерируют массу сообщений, которые лучше отделить от прочих. Для этого задаются правила фильтров в файле /etc/syslog-ng/syslog-ng.conf. В нем источники, места назначения и фильтры представлены объектами, а связывают их записи в лог-файле. В конфигурации по умолчанию стандартный источник определяется так:
source src {
unix-stream(“/dev/log” max-connections(256));
internal();
file(“/proc/kmsg”);
};
Здесь создан объект источника src, принимающий записи журнала от разных источников. Затем определим места назначения:
destination messages { file(“/var/log/messages”); };
destination console_all { file(“/dev/tty12”); };
Первая строка выводит записи в указанный файл, вторая – в консоль. В этом можно убедиться, нажав Ctrl + Alt + F12 или перейдя в стандартную консоль входа в систему 1 (Ctrl + Alt + F1 с рабочего стола) и затем нажав Alt+стрелка влево. Источник и место назначения готовы; теперь определим формат записей, отправляемых с первого на второе. В конфигурации по умолчанию стандартный источник отправляется в оба места назначения.
log { source(src); destination(messages); };
log { source(src); destination(console_all); };
Здесь можно добавить новые источники или места назначения и фильтры, определяющие, что куда отправить. Вот пример, где вывод почтового сервера посылается в отдельный файл mail.log:
destination d_mail { file(“/var/log/mail.log”); };
filter f_mail { facility(mail); };
filter f_notmail { not facility(mail); };
Строки с источником нет – мы все еще пользуемся стандартным источником. В качестве места назначения задается отдельный лог-файл для почты, а два фильтра с помощью функции facility определяют, какие сообщения приходят от почтового сервера. Есть несколько стандартных групп – например, mail, auth или news (в документации есть полный список), и при отправке сообщения процесс указывает одну из групп. Преимущество такого подхода в том, что не нужно знать имя процесса: сообщения будут отфильтрованы для любой почтовой программы. Второй фильтр работает как отрицание и выбирает все сообщения не от почты. Имена объектов источника (source), фильтра (filter) и места назначения (destination) обычно предваряются префиксами s_, f_ и d_, чтобы было сразу понятно, какой объект следует за префиксом. Теперь заменим первые две строки на следующие:
log { source(src); filter(f_notmail); destination(messages); };
log { source(src); filter(f_mail); destination(d_mail); };
Теперь между источником местом назначения появился фильтр, и в лог-файл попадут только должные сообщения. Не создай мы фильтра notmail, оставив исходную строку, сообщения попали бы не только в лог-файл почты, но и в лог-файл по умолчанию. Но сообщения по-прежнему отправляются в консоль, так как этого мы не меняли. При любых изменениях в конфигурационном файле нужно сообщить syslog-ng о том, что нужно перечитать его, отправив ей сигнал SIGHUP таким образом:
sudo killall -HUP syslog-ng
Держим это под контролем
Если ваш корневой раздел (/) начал переполняться, проверьте содержимое /var. Вышедший из-под контроля процесс может писать в свой лог-файл огромный объем данных, быстро съедая ценное место на диске. Это одна из причин, по которым многие предпочитают размещать /var на отдельном разделе. Переполнение раздела / способно вызвать нехорошие последствия для системы.
Со временем содержимое каталога /var/log будет отнимать все больше места на диске. Чтобы решить эту проблему, установим logrotate. Она запускает cron, обычно раз в день, и архивирует лог-файлы в соответствии с правилами в /etc/logrotate.conf и /etc/logrotate.d. /etc/logrotate.conf – общий конфигурационный файл, а в /etc/logrotate.d находятся отдельные наборы правил, применяемые к конкретным пакетам или лог-файлам. В общем конфигурационном файле находятся настройки вроде
weekly
rotate 4
create
compress
которые означают, что по умолчанию лог-файлы архивируются еженедельно, хранится до четырех последних копий, при архивировании текущего создается новый пустой файл, и что файлы сжимаются. На практике это означает, что основной лог-файл messages упаковывается в messages.1.gz и создается новый пустой файл messages. При следующей архивации messages.1.gz переименовывается в messages.2.gz и создается новый messages.1.gz. Четвертый файл удаляется, чтобы расчистить дорогу остальным. К параметрам можно добавить dateext, и вместо цифр 1, 2 и 3 к именам файлов будет добавляться дата. Файл для syslog-ng в /etc/logrotate.d будет выглядеть примерно так:
/var/log/messages {
postrotate
/etc/init.d/syslog-ng reload > /dev/null 2>&1 || true
endscript
}
Здесь указываются архивируемый файл (его имя может задаваться шаблоном) и правила. В данном случае единственное правило, особенное для этого файла – команда postrotate, выполняемая после завершения архивации, чтобы syslog-ng перечитал конфигурационный файл. Это также снимает блокировку со старого лог-файла и открывает новый. Здесь можно указать любые параметры из глобального файла чтобы перезагрузить их. Например, можно хранить более длинную историю для конкретного лог-файла, включив параметр:
rotate 8
Если вас беспокоит непомерное увеличение размера лог-файлов, когда пошедшая вразнос программа будет писать туда слишком много сообщений, добавьте параметр
maxsize 10M
для принудительной архивации при достижении размера файла в 10 МБ, даже если время архивации еще не пришло. Обратите внимание, что это произойдет только при запуске задания cron, поэтому файл может успеть стать намного больше. Однако лог-файлы хорошо сжимаются, и сжатие разбухшего файла высвобождает много свободного места.
Просматривать лог-файлы вручную не обязательно: есть программы, которые проанализируют их и сформируют отчет. Такие программы как logwatch (www.logwatch.org) и logcheck (http://packages.debian.org/sid/logcheck) просканируют системные лог-файлы и отправят вам отчет с предупреждениями о любых аномалиях. Есть и программы, которые строят диаграммы для лог-файлов конкретных приложений – например, диаграммы трафика через Apache.
Пока мы говорили только о чтении лог-файлов, но командой logger в системный лог можно записать данные и из оболочки (или скрипта), примерно так:
logger -i -t myscript “Ваш скрипт рухнул”
Параметр -t помечает запись, параметр -i добавляет в журнал идентификатор процесса, а за ними следует сообщение. |