Шаблоны (Templates) rsyslog

Linux > Шаблоны (Templates) rsyslog
08.12.2015 21:16:19



Статья:

Очень важной и ключевой особенностью rsyslogd является возможность использования шаблонов. Template позволяет: 1. задавать формат выводимой информации, 2. использовать динамические имена файлов логов на основании какого-либо правила. На самом деле, все выходные сообщения в rsyslogd формируются на основе шаблонов. Тут может возникнуть соответствующий вопрос - как же вывод формируется, если не указать никаких шаблонов в rsyslog.conf (ведь по умолчанию не указано никаких шаблонов)? Все просто. Имеются некоторые шаблоны (взятые из совместимые со старой версии syslog и статично прописанные в исходники rsyslog). Подтверждение этого дела можно найти в файле исходного кода syslogd.c, поиском по строке "template_" (наткнетесь на /* hardcoded standard templates (used for defaults) */). Шаблоны должны быть заданы до использования в правилах.

Cинтаксис template
В целом, структуру шаблона можно представить в следующем виде синтаксисе:

$template имя_шаблона,описание_шаблона[,опции(по_необходимости)]
Давайте разберем каждый пункт. $template - указывает, что далее пойдет описание шаблона. имя_шаблона - произвольное значение понятно описывающее, что за шаблон и для чего (имя будет использоваться в правилах для обращения к шаблону). опции - может принимать значение sql и sqlstd, это заставляет отформатировать конечный результат выполнения шаблона в вид, пригодный для MySQL или стандартный SQL соответственно (фактически - заменяет некоторые спецсимволы в syslog сообщении в формат, поддерживаемый SQL-сервером). Опции применяются только для шаблонов для вывода в sql.

описание_шаблона заключается в кавычки. В шаблонах в кавычках любой текст воспринимается буквально (как есть), кроме того текста, который заключен в знаки процентов (%текст%). Такой текст является переменной и позволяет "получить доступ" к внутреннему содержимому пришедшего сообщения и тем самым добиться всяких веселых фич по модификации ). Так же, в кавычках может использоваться т.н. escape-последовательности в виде обратной косой черты и некоего символа за чертой (например, \n - новая строка, \7 - ...).

Применение переменных в шаблонах rsyslog
Давайте разгребем структуру значений, указываемых в %процентах%.

%имя_proper[:начало_строки:конец_строки:опции[:fieldname]]%
имя_proper (оно же имя_свойства, оно же имя_переменной) - задает имя свойства (свойство в данном контексте можно рассматривать как некоторое свойство\поле syslog сообщения, проходящего сквозь демона), вот некоторые наиболее используемые свойства rsyslog:

  • msg - тело сообщения
  • hostname - имя хоста\ip из сообщения
  • fromhost - имя хоста, от которого пришло сообщение
  • fromhost-ip - адрес хоста, от которого пришло сообщения (127.0.0.1 для локальных сообщений)
  • syslogtag - имя и номер процесса (" rsyslogd[12125]:"), который выдал сообщение (извлекается из сообщения)
  • programname - имя процесса, который выдал сообщение (извлекается из сообщения)
  • pri - источник и приоритет, в виде числа
  • pri-text - декодированные источник и приоритет (facility.priority, например syslog.emer)
  • syslogfacility - только источник в виде числа
  • syslogfacility-text - только декодированный источник ("local0")
  • syslogseverity - только приоритет в виде числа
  • syslogseverity-text - только декодированный уровень ("debug")
  • timegenerated - время получения  (с высоким разрешением)
  • timereported - время, извлечённое из сообщения
  • inputname - имя входного модуля
  • $hour, $minute - текущее время
  • $myhostname - имя хоста обработки

Значения начало_строки:конец_строки - мозговыносящие. Победить их можно где-то тут. Кратко - они используются для регулярных выражений.

Далее - опции. Опции позволяют модифицировать переменную в границе от знака процента до знака процента. Можно применять одновременно несколько опций, через запятую. Если указать несколько противоречащих (например uppercase, lowercase), то будет применена последняя указанная (lowercase). Вот некоторые опции:

uppercase - преобразование к верхнему регистру
lowercase - преобразование к нижнему регистру
date-mysql - преобразовать в формат даты MySQL
space-cc - заменить управляющие символы пробелами
drop-cc - удалить управляющие символы
и еще куча
fieldname - данное поле доступно с версии 6.3.9+ и имеет очень специфичный характер. Можно ее забыть...

Как видно из приведенного выше шаблона переменной, значения из фигурных скобок указываются по желанию, то есть можно указать просто, например %hostname%. Но если будут применяться опции, то необходимо указать и предыдущие пустые поля, например %hostname:::lowercase%. Между двоеточиями пропущены поля начало_строки и конец_строки. При этом, fieldname почему-то в качестве пустого - не указывается.

Шаблоны, которые хардово запрограммированы в rsyslog (но которые можно изменить директивой $ActionFileDefaultTemplate):

RSYSLOG_SyslogProtocol23Format - формат, определённый в проекте стандарта IETF ietf-syslog-protocol-23, соответствует шаблону:

"<%PRI%>1 %TIMESTAMP:::date-rfc3339% %HOSTNAME% %APP-NAME% %PROCID% %MSGID% %STRUCTURED-DATA% %msg%\n\"
RSYSLOG_FileFormat - традиционный формат журнала, с добавлением долей секунды и зоны, соответствует шаблону:

"%TIMESTAMP:::date-rfc3339% %HOSTNAME% %syslogtag%%msg:::sp-if-no-1st-sp%%msg:::drop-last-lf%\n\"
RSYSLOG_TraditionalFileFormat - традиционный формат журнала для записи в файл, соответствует следующему шаблону:

"%TIMESTAMP% %HOSTNAME% %syslogtag%%msg:::sp-if-no-1st-sp%%msg:::drop-last-lf%\n\"
RSYSLOG_ForwardFormat - традиционный формат журнала для передачи с добавлением долей секунды и зоны, соответствует шаблону:

"<%PRI%>%TIMESTAMP:::date-rfc3339% %HOSTNAME% %syslogtag:1:32%%msg:::sp-if-no-1st-sp%%msg%\"
RSYSLOG_TraditionalForwardFormat - традиционный формат журнала для передачи на удалённый сервер

"<%PRI%>%TIMESTAMP% %HOSTNAME% %syslogtag:1:32%%msg:::sp-if-no-1st-sp%%msg%\"
Правила сортировки rsyslog (Rule line)

Каждая строка правил сортировки имеет классический формат, как и в обычном сислоге. Для понимания, что и как, необходимо почитать статью syslog. Кратко: правило состоит из селекотора и действия, разделенных пробелом или табулятором. Селектор в свою очередь состоит из источника и приоритета. Каждое сообщение сверяется с селектором из каждого правила последовательно, если селектор сообщения и правила совпадает, то выполняется указанное действие. При этом, после первого совпадения - обработка не останавливается. Перед действием, мессадж преобразуется в соответствии с шаблоном (шаблон по умолчанию, заданный в соответствующей директиве (заменяющий шаблон по умолчанию), заданный в данном действии шаблон - один из трех).

К стандартным возможностям селекторов syslog добавились некоторые дополнительные возможности (напомню, что классически селектор - это источник.приоритет, он же facility.priority). В rsyslog в качестве селектора можно использовать значения переменных. В rsyslog применение переменных в селекторе называется Filters (фильтры). Выше в статье, а так же в первой статье о syslog описан классический подход к фильтрации на основе источник.приоритет (т.н."traditional" severity and facility based selectors). Кроме традиционной фильтрации существует следующие виды фильтрации: RainerScript-based filters (фильтрация на основе языка RainerScript - фактически обычный if - then - else), property-based filters (фильтрация на основе свойств сообщения (как в template)). Давайте рассмотрим оба:

Фильтрация RainerScript (RainerScript-based filters)
Как я уже сказал, RainerScript - это классический язык на основе if then else. В rsyslog RainerScript поддерживает вложенность условий, арифметические, логические и строковые операции. В целом, синтаксис следующий:

if условие then блок_действий else блок_действий
Соответственно, if, then - это обязательные операторы, определяющие конструкцию условия, else - по необходимости. блок_действий - может содержать одно действие (action), либо вложенный блок условий. Если блок условий содержит несколько действий, то он заключается в скобки. условие - содержит условие отбора сообщений для блока_действий. В условии можно использовать:

логические выражения (and, or, not), а так же группировку данных выражений в виде: not условие0 and (условие1 and условие2).
переменные (properties) - переменные указываются в виде $имя_переменной (например $hostname или $msg)
операции сравнения (== - равно, != - не равно, > - больше, < - меньше, <= - меньше или равно, >= - больше или равно, (!)contains - (не)содержит, (!)startswith - (не)начинается с)
комментарии /* комментарии */ (сомнительный пункт ...нужно ли его экранировать как в bash ???)
Описание языка есть на сайте. Маленький пример фильтра на основе RainerScript:

if $syslogfacility-text == 'local7' and $msg startswith 'CISCO' and ($msg contains 'warn' or $msg contains 'emer') then /var/log/cisco-alarm

фильтрация на основе свойств сообщения (property-based filters)
Давайте рассмотрим данный вид фильтрации.

:переменная, [!]операция_сравнения, "искомое_значение" действие

Что у нас тут есть: переменная - в соответствии с переменными,(в данном случае - без % или $), действие выполняемое над сообщением. операция_сравнения - может быть:

contains - проверяет соответствие искомое_значение с любой частью строки в переменная
isequal - проверяет, совпадает (целиком) ли искомое_значение с переменной
isempty - проверяет, является ли переменная пустой (доступна с 6.6.2)
startswith - проверяет, начинается ли переменная с искомое_значение
regex или ereregex - сравнивает содержимое переменной, заданному в искомое_значение регулярному выражению в соответствии с regular и Extended Regular Expression соответственно
Например: :msg, contains, "syslog" будет искать слово syslog в теле.

Существует так же, специальный символ &, который повторяет выполнение прошлого фильтра и запускает действие, указанное после данного символа. Это очень удобно для фильтрации или экономии системных ресурсов, например:

# экономим ресурсы:
*.=crit /var/log/somefile
& root
& /var/log/criticalmessages
# фильтруем сообщения
*.* /var/log/allmsgs-incl-informational.log
:msg, contains, "informational" ~
*.* /var/log/allmsgs-no-informational.log
то есть в первом варианте, rsyslogd нет необходимости несколько раз сравнивать селектор. Сообщение просто выполняет 3 действия.

Действия (actions)
Действия rsyslog полностью совместимы с действиями syslog. Так же, стоит учитывать, что в действии rsyslog, кроме стандартный значений syslog, добавились дополнительные (выделены цветом):

/путь/к/файлу - отправить сообщения в простой файл (по умолчанию, rsyslogd умеет сам создавать новые файлы)
?имя_шаблона - вместо классического действия (/путь/к/файлу) в rsyslog можно указывать шаблон, в соответствии с которым будет динамически формироваться новый файл по заданному в шаблоне правилу.
?имя_шаблона;шаблон_фильтра - дополнительно, к шаблону имени файла (?имя_шаблона) возможно преобразовать сообщения поступающие в эти файлы в соответствии с заданным шаблоном фильтра (шаблон_фильтра).
|/путь/к/fifo - отправить в именованный канал
/dev/терминал или /dev/консоль - отправить на указанную консоль\терминал
@имя-хоста-udp[:порт] - отправить на удаленный хост по UDP
@@[модификаторы]имя-хоста-tcp[:порт]- отправить на удаленный хост по TCP, модификаторы указывают:
zцифра - задает gzip сжатие отправляемых пакетов с уровнем сжатия заданным цифрой от 0-9 (9-максимальное)
список пользователей через запятую - отправить на терминал сообщение указанным пользователям
* - отправить всем пользователям (аналог команды wall)
:имя_модуля_вывода:параметры_модуля[:имя_шаблона] - отправляет сообщение в модуль вывода с заданными параметрами и заданным шаблоном (по желанию)
~ (тильда) - после данного символа сообщение будет удалено и дальнейшая обработка не продолжится
^имя_программы[;имя_шаблона] - можно написать свой обработчик сообщений, ему на stdin будет отправлено содержимое в соответствии с шаблоном