====== Журналы / логи ====== ===== journalctl ===== Управление сервисами в т.ч. и логами в системе, происходит системой инициализации **systemd**.\\ Хранит журналы в бинарном виде. Находится выше по иерархии чем **syslogd** и принимает события от него в т.ч. * **-f** - выводить новые сообщения в реальном времени. * **-e, --pager-end** - только последние сообщения. * **-n** - кол-во строк. * **-x, --catalog (--list-catalog)** - добавляет пояснения (максимальный уровень подсказок). * **-u, --unit** - выбранный сервис. * **-k, --dmesg** - сообщения только ядра (аналог **dmesg**). * **--system** - только системные сообщения. * **-b (--list-boots)** - логи последней загрузки (список доступных загрузок). * **-o** - формат вывода логов (json-pretty, verbose, cat и т.д.). * **-p** - приоритет. ==== Управление файлами ==== Задается максимальное доступное место на диске, по достижении, сообщения удаляются с конца.\\ Задается в параметрах **SystemMaxUse=** и **RuntimeMaxUse=** в файле **/etc/systemd/journal.conf**.
:!: Последняя загрузка системы/перезапуск Перезагрузка считается инициированной входом в нее псевдопользователя "reboot"\\ # Врмя последней загрузки who -b # История логинов last [имя пользователя] # Так к вопросу о перезагрузке last -x | head | tac или last reboot # (подвопросом) Список зарегистрированных загрузок системы journalctl --list-boots # более подробная инфа journalctl -b {num} -n
===== Rsyslog ===== [[https://www.rsyslog.com/|Оф сайт]]\\ [[https://rsyslog.readthedocs.io/en/latest/configuration/modules/index.html|Тут тоже неплохая дока]] [[https://www.k-max.name/linux/rsyslog-na-debian-nastrojka-servera/|Rsyslog на Debian, настройка сервера сбора логов]]\\ [[https://selivan.github.io/2017/02/07/rsyslog-log-forward-save-filename-handle-multi-line-failover.html|Конфигурация Rsyslog]]\\ [[http://devel.aanet.ru/rsyslog-v5/property_replacer.html|Заменитель свойств]]\\ Замена старой **syslog**, принимает и обрабатывает лог-записи, есть несколько вариантов входа, в основном псевдоустройство **/dev/log**, так же может брать из файлов, сети и т.д., регулируется подключаемыми модулями\\ Конфигурация в файле **/etc/rsyslog.conf**, либо "/etc/rsyslog.d/50-default.conf", так же подтягиваются файлы *.conf из папки **/etc/rsyslog.d**, для пользовательской конфигурации.\\ При сетевой передаче рекомендуется использовать протокол **Relp**, специальный для этой утилиты, более надежный в сравнении с **tcp**.\\ Формат **RainerScript** позволяет задавать С-подобные правила обработки сообщений. **Со старыми директивами** могут быть проблемы, поэтому **не следует использовать его с устаревшими директивами**\\ Обработка происходит в блоках **RuleSet**, все что не входит в эти блоки, входит в блок по умолчанию.\\ Так же, поступающие сообщения **парсятся**, так же есть парсер по умолчанию, извлекает **части сообщения**, типа $msg, $rawmsg, $fromhost, $syslogtag, $programname и т.д.\\ Для остановки процесса после обработки команда **stop**\\ Некоторые модули для использования в действиях () * omfile - вывод файла * omfwd - сетевая переадресация по udp или tcp * omrelp - сетевая переадресация по протоколу RELP * onmysql , ompgsql , omoracle — вывод в базу данных
:!: Примеры Запишите все сообщения средств auth и authpriv в файл /var/log/auth.logи продолжите обработку этих сообщений: # legacy auth,authpriv.* /var/log/auth.log # modern if ( $syslogfacility-text == "auth" or $syslogfacility-text == "authpriv" ) then { action(type="omfile" file="/var/log/auth.log") } Записать все сообщения с именем программы, начинающимся с «haproxy» в файл /var/log/haproxy.log, не сбрасывать буфер после каждого сообщения и прекратить дальнейшую обработку: # legacy (note the minus sign in front of filename - it disables buffer flush) :programname, startswith, "haproxy", -/var/log/haproxy.log & ~ # modern if ( $programname startswith "haproxy" ) then { action(type="omfile" file="/var/log/haproxy.log" flushOnTXEnd="off") stop } # we can mix legacy and modern if $programname startswith "haproxy" then -/var/log/haproxy.log &~ Простой вариант условия if $syslogtag == 'example' then /var/log/test/out.log # Либо легаси подход :programname, contains, "MyProgram" /var/log/MyProgram.log
Для вывода сообщений можно использовать **шаблон**, задается директивой ([[http://devel.aanet.ru/rsyslog-v5/rsyslog_conf_templates.html|Тут есть описание]]) * Старый формат - $template DynFile,"/var/log/system-%HOSTNAME%.log" * Новый формат - template(name="myMsg" type="string" string="\n%msg%\n") - **Не работает внутри If'a**
:!: Имена файлов Вариант чтения всех файлов по маске и сохранения оригинального имени на выходе input(type="imfile" File="/srv/myapp/logs/*.log" Tag="myapp__" Ruleset="myapp_logs" addMetadata="on") ruleset(name="myapp_logs") { set $.suffix=re_extract($!metadata!filename, "(.*)/([^/]*)", 0, 2, "all.log"); # Либо можно функцией field() #set $.originfilename=field($!metadata!filename, 47, 7); call sendToLogserver } Динамические имена файлов на выходе # Легаси подход $template DynFile, "/var/log/test/test-%syslogtag%.log" *.* ?DynFile;myTemlpate # Новый подход template (name="DynFile" type="string" string="/var/log/test/test-%syslogtag%.log") action(type = "omfile" dynaFile="DynFile" template="myTemlpate")
:!: Еще пример Сервер $MaxMessageSize 64k module(load = "imfile" mode="inotify") module(load = "omrelp") # Вход из файлов, отмечаем его тегами input(type="imfile" File="/fold/BIN/Import/*/log/*.log" Tag="SendImport") input(type="imfile" File="/fold/BIN/ErrImport/*/log/*.log" Tag="SendErrImport") # Из метаданных файла берем имя файла и название папки оно же название импорта set $.filename=field($!metadata!filename, 47, 7); set $.importname=field($!metadata!filename, 47, 5); # Формат выходного сообщения. К sysтегу добавляем имя импорта и имя папки template(name="outFormatMessage" type="string" string="<%PRI%>%TIMESTAMP% %HOSTNAME% %syslogtag%%$.importname%__%$.filen$ # Отправляем по сети if ($syslogtag == 'SendImport') then { action(type="omrelp" Target="10.0.0.0" Port="20514" Template="outFormatMessage") stop } if ($syslogtag == 'SendErrImport') then { action(type="omrelp" Target="10.0.0.0" Port="20515" Template="outFormatMessage") stop } Клиент $MaxMessageSize 64k module(load="imrelp") input(type="imrelp" port="20514" ruleset="MImport") input(type="imrelp" port="20515" ruleset="MErrImport") # Формат выходного сообщения template(name="outFormatMessage" type="string" string="%msg%\n") # Динамическое имя файла template(name="ImportFileName" type="string" string="/fold/ImportLogs/Import/%$.ffilename%") template(name="ErrImportFileName" type="string" string="/fold/ImportLogs/ErrImport/%$.ffilename%") ruleset(name="MImport") { # Извлекаем из переданных данных имя файла и сервиса set $.ffilename = replace($programname, "__", "/"); set $.ffilename = replace($.ffilename, "SendImport", ""); # Сохраняем в файл action(type ="omfile" dynaFile="ImportFileName" template="outFormatMessage" fileOwner="AppServer" fileGroup="AppServer" dirOwner="AppServer" dirGroup="AppServer" dirCreateMode="0775" FileCreateMode="0664") } ruleset(name="MErrImport") { # Извлекаем из переданных данных имя файла и сервиса set $.ffilename = replace($programname, "__", "/"); set $.ffilename = replace($.ffilename, "SendErrImport", ""); # Сохраняем в файл action(type ="omfile" dynaFile="ErrImportFileName" template="outFormatMessage" fileOwner="AppServer" fileGroup="AppServer" dirOwner="AppServer" dirGroup="AppServer" dirCreateMode="0775" FileCreateMode="0664") }
===== Ротация файлов. Logrotate ===== [[https://www.opennet.ru/man.shtml?topic=logrotate&category=8&russian=0|Есть описание параметров]]\\ [[https://mnorin.com/logrotate-nastrojka-rotatsii-logov.html|Гораздо более полный перечень параметров]]\\ Утилита **Logrotate**, основная конфигурация **/etc/logrotate.conf**, в папке **/etc/logrotate.d/** отдельные конфиги\\ Сама утилита запускается раз в день, в планировщике есть файл- **/etc/cron.daily/logrotate**\\ Без порядковых номеров ротация перестает работать\\ Основной конфиг запускается раз в день, поэтому **часовой интервал игнорируется**, для часа можно поместить в **/etc/cron.hourly/**, для меньшего интервала нужно создать отдельный конфиг (в другом месте для того чтобы не пересекаться с ежедневным), смысл в том чтобы запускать ее через крон самостоятельно, для этого настроим задачу:\\ # Создали файл конфига nano /home/sammy/logrotate.conf # Запускаем вручную (-d для тестирования) logrotate /home/sammy/logrotate.conf [--verbose --force] # Добавляем в крон "15 * * * * /usr/sbin/logrotate /home/sammy/logrotate.conf" Ротировать можно как регулярно (**по времени**) так и **по размеру** файла\\ Можно выполнять скрипты до и после ротации\\ Параметры:\\ * **hourly/daily/weekly/monthly** - периоды * **rotate 3** - хранить 3 последних файла * **size** - планка размера для ротирования (size 100, size 100k, и size 100M) * **compress** - сжимать * **delaycompress** - кроме последнего и предпоследнего * **dateext** - к имени архивного файла добавляется дата ротации в формате (%Y%m%d) вместо номера * **copytruncate** - ротируется копия, оригинал урезается * **create** - ротируется оригинал, рабочий создается новый
:!: Образец конфига /var/log/messages # файл для работы, можно указать маску { daily rotate 3 # хранить 3 последних файла compress # сжимать delaycompress # кроме последнего и предпоследнего dateext # к имени архивного файла добавляется дата ротации в формате (%Y%m%d) вместо номера } Если переименовываем файл после ротации. **Его нужно перемещать** создавать копию, без номеров ротация перестает работать\\ /usr/zxbcps/files/zx.tar { rotate 3 sharedscripts # Для того чтобы скрипт выполнялся один раз postrotate mv /usr/zxbcps/files/zx.tar.1 /usr/zxbcps/files/zzx_$(date +%Y-%m-%d_%H:%M).tar endscript }