Содержание

Журналы / логи

journalctl

Управление сервисами в т.ч. и логами в системе, происходит системой инициализации systemd.
Хранит журналы в бинарном виде. Находится выше по иерархии чем syslogd и принимает события от него в т.ч.

Управление файлами

Задается максимальное доступное место на диске, по достижении, сообщения удаляются с конца.
Задается в параметрах SystemMaxUse= и RuntimeMaxUse= в файле /etc/systemd/journal.conf.

:!: Последняя загрузка системы/перезапуск

Перезагрузка считается инициированной входом в нее псевдопользователя «reboot»

  # Врмя последней загрузки
who -b 
 
  # История логинов
last [имя пользователя]
 
  # Так к вопросу о перезагрузке
last -x | head | tac
или 
last reboot
 
  # (подвопросом) Список зарегистрированных загрузок системы
journalctl --list-boots
  # более подробная инфа
journalctl -b {num} -n 

Rsyslog

Оф сайт
Тут тоже неплохая дока Rsyslog на Debian, настройка сервера сбора логов
Конфигурация Rsyslog
Заменитель свойств

Замена старой 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
Некоторые модули для использования в действиях ()

:!: Примеры

Запишите все сообщения средств 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

Для вывода сообщений можно использовать шаблон, задается директивой (Тут есть описание)

:!: Имена файлов

Вариант чтения всех файлов по маске и сохранения оригинального имени на выходе

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

Есть описание параметров
Гораздо более полный перечень параметров

Утилита 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"

Ротировать можно как регулярно (по времени) так и по размеру файла
Можно выполнять скрипты до и после ротации

Параметры:

:!: Образец конфига
/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
}