Збір логів з rsyslog, іменами файлів в тегах, багаторядковими повідомленнями і відмовостійкість

image
зображення з сайту oxygen-icons.org
Завдання
Передавати лог-файли на центральний сервер. Коли сервер не втрачати повідомлення, а накопичувати і передавати при його появу в мережі. Коректно передавати багаторядкові повідомлення.
Додатково:
  • не потрібно зміна конфігурації сервера при появі нових лог-файлів, досить перенастроювання клієнта.
  • можна передавати вміст всіх лог-файлів з відповідним шаблоном ім'ям, причому на сервері їх вміст буде зберігатися роздільно у файли з таким же ім'ям.
Умови: в інфраструктурі використовуються тільки Linux-сервера.
Вибір софта
Навіщо взагалі потрібен syslog-сервер, коли є elastic beats, logstash, systemd-journal-remote і ще багато нових блискучих технологій?
  • Це стандарт для ведення логів у POSIX-сумісних системах.
    Деякий софт, наприклад haproxy, використовує тільки його. Тобто зовсім позбудеться syslog вам все одно не вдасться
  • Його використовує мережеве залізо
  • Складніше у налаштуванні, але багатший за можливостями, ніж альтернативні рішення.
    Наприклад, Elastic Filebeat досі не вміє inotify.
  • Невимогливий до пам'яті. Можливе використання на вбудованих системах після невеликого тюнінгу.
  • Дозволяє змінювати повідомлення перед збереженням/пересилкою.
    Дивна завдання, але іноді потрібно. Наприклад, PCI DSS у розділі 3.4 вимагає маскувати або шифрувати номери карт, якщо вони зберігаються на диск. Тонкість в тому, що якщо хтось ввів номер картки в рядок пошуку або форму зворотного зв'язку, то як тільки ви зберегли запит в лог, ви порушуєте стандарт.
Спостереження: користувачі намагаються ввести номер картки у будь-яке поле вводу на сторінці, і норовлять повідомити його саппорт разом з CVV і PIN.
Формат повідомлень і legacy
TLDR: все поганоSyslog з'явився в 80-х, і швидко став стандартом логування для Unix-like систем і мережевого устаткування. Стандарту не було, всі писали за принципом сумісності з існуючим софтом. У 2001 IETF описав поточний стан речей в RFC 3164(статус "informational"). Т. к. реалізації дуже відрізняються, зокрема у цьому документі сказано "зміст будь-якого IP-пакету відправленого на UDP порт 514 повинно розглядатися як повідомлення syslog". Потім спробували стандартизувати формат в RFC 3195, але документ вийшов невдалим, для нього в даний момент немає жодної живої реалізації. У 2009 взяли RFC 5424, визначає структуровані повідомлення, але цим рідко хто користується.
Ось тут можна прочитати, що про все це думає автор rsyslog Рейнер Герхард(Rainer Gerhards). Фактично, як і раніше, все реалізують syslog як попало, і завдання інтерпретувати все це розмаїття лягати на syslog-сервер. Наприклад, в rsyslog включений спеціальний модуль для розбору формату, що використовується CISCO IOS, ну і для самих поганих випадків починаючи з п'ятої версії можна визначати власні парсери.
Повідомлення syslog при передачі по мережі виглядають приблизно так:
<PRI> TIMESTAMP HOST TAG MSG

  • PRI
    — Priority. Обчислюється як
    facility * 8 + severity
    .
    • Facility(категорія) приймає значення від 0 до 23, їм відповідають різні категорії системних служб: 0 — kernel, 2 — mail, 7 — news. Останні 8 — від local0 до local7 — визначені для служб, що не потрапляють у зумовлені категорії. Повний список.
    • Severity(важливість) приймає значення від 0(emergency, найвища) до 7(debug, найнижча). Повний список.
  • TIMESTAMP
    — час, зазвичай у форматі "Feb 6 18:45:01". Згідно RFC 3164, може записуватися в форматі часу ISO 8601: "2017-02-06T18:45:01.519832+03:00" з більшою точністю і з урахуванням використовуваної тимчасової зони.
  • HOST
    — ім'я хоста, сгенерировавшего повідомлення
  • TAG
    — містить ім'я програми, сгенерировавшей повідомлення. Не більше 32 алфавітно-цифрових символів, хоча за фактом багато хто реалізації дозволяють більше. Будь-алфавитноцифровой символ закінчує TAG і починає MSG, зазвичай використовується двокрапка. Іноді в квадратних дужках містить номер сгенерировавшего повідомлення процесу. Т. к.
    [ ]
    — не алфавітно-цифрові символи, то номер процесу разом з ними повинен вважатися частиною повідомлення. Але зазвичай всі реалізації вважають це частиною тега, вважаючи повідомленням всі після символів ": "
  • MSG
    — повідомлення. Через невизначеність з тим, де ж закінчується тег і починається повідомлення, початок може додаватися пробіл. Не може містити символи перекладу рядка: вони є роздільниками фреймів, і почнуть нове повідомлення. Способи все ж переслати мгногострочное повідомлення:
    • екранування. Отримаємо на стороні приймача текст
      #012
      замість перекладів рядка
    • використання octet-counted TCP Framing, як визначено в RFC 5425 для TLS-enabled syslog. Нестандарт, тільки деякі реалізації.

Альтернатива: RELP

Якщо повідомлення пересилаються між хостами, використовують rsyslog, можна замість plain TCP sysog використовувати RELP — Reliable Event Logging Protocol. Був створений для rsyslog, зараз підтримується і деякими іншими системами. Зокрема, його розуміють Logstash і Graylog. Для транспорту використовує TCP. Може опціонально шифрувати повідомлення з допомогою TLS. Надійніше plain TCP syslog, не втрачає повідомлення при розриві з'єднання. Вирішує проблему з багаторядковими повідомленнями.
Конфігурація rsyslog
На відміну від другої поширеною альтернативи, syslog-ng, rsyslog сумісний з конфіг історичного syslogd:
auth,authpriv.* /var/log/auth.log
*.*;auth,authpriv.none /var/log/syslog
*.* @syslog.example.net

оскільки можливості rsyslog набагато більше, ніж у його попередника, формат конфіги був розширений додатковими директивами, що починаються зі знака
$
:
$ActionFileDefaultTemplate RSYSLOG_TraditionalFileFormat
$WorkDirectory /var/spool/rsyslog
$IncludeConfig /etc/rsyslog.d/*.conf

Починаючи з шостої версії, з'явився сі-подібний формат RainerScript, що дозволяє задавати складні правила обробки повідомлень.
оскільки все це робилося поступово та з урахуванням сумісності зі старими конфіг, то в підсумку вийшла пара неприємних моментів:
  • деякі плагіни(я поки що з такими не стикався) можуть не підтримувати новий RainerScript стиль налаштувань, їм потрібні старі директиви
  • настройка через старі директиви не завжди працює як очікується для нового формату:
    • якщо модуль
      omfile
      викликається за допомогою старого формату:
      auth,authpriv.* /var/log/auth.log
      , то власник і дозволу отриманого файлу регулюються старими директивами
      $FileOwner
      ,
      $FileGroup
      ,
      $FileCreateMode
      . А ось якщо він викликається за допомогою
      action(type="omfile" ...)
      , то ці директиви ігноруються, і треба налаштовувати параметы action або задавати при завантаженні модуля
    • Директиви виду
      $ActionQueueXXX
      налаштовують тільки ту чергу, яка буде використана в першому action після них, потім значення скидаються.
  • крапки з комою десь заборонені, а десь навпаки обов'язкові(друге рідше)
Щоб не спотикатися про ці тонкощі(так, вони описані в документації, але хто ж її цілком читає?), варто слідувати простим правилам:
  • для маленьких простих конфіги використовувати старий формат:
    :programname, startswith, "haproxy" /var/log/haproxy.log
  • для складної обробки повідомлень і для тонкої настройки Actions завжди використовувати RainerScript, не чіпаючи legacy директиви виду
    $DoSomething
Детальніше про формат конфига здесь.
Обробка повідомлень
  • Усі повідомлення приходять з Input(їм може бути багато) і потрапляють на обробку в прив'язаний до нього RuleSet. Якщо це явно не вказано, то повідомлення потраплять в RuleSet за замовчуванням. Всі директиви обробки повідомлень, не винесені в окремі RuleSet-блоки, відносяться саме до нього. Зокрема, до нього відносяться всі директиви з традиційного формату конфіги:
    local7.* /var/log/myapp/my.log
  • Input прив'язаний список парсерів для розбору повідомлення. Якщо явно не вказано, буде використовуватися список парсерів для розбору традиційного формату syslog
  • Парсер виділяє з повідомлення властивості. Найбільш використовувані:
    • $msg
      повідомлення

    • $rawmsg
      — повідомлення цілком до обробки парсером
    • $fromhost
      ,
      $fromhost-ip
      — DNS ім'я та IP адресу хоста-відправника
    • $syslogfacility
      ,
      $syslogfacility-text
      — facility в числової і текстової формі
    • $syslogseverity
      ,
      $syslogseverity-text
      — то ж для severity
    • $timereported
      — час з повідомлення
    • $syslogtag
      — поле TAG
    • $programname
      — поле TAG з відрізаним id процесу:
      named[12345]
      ->
      named
    • весь список можна переглянути тут
  • RuleSet містить список правил, правило складається з фільтра і прив'язаних до нього одного або кількох Actions
  • Фільтри — логічні вирази, з використанням властивостей повідомлення. Детальніше про фільтри
  • Правила застосовуються послідовно до повідомлення, потрапив у RuleSet, на першому спрацювання правилі повідомлення не зупиняється
  • Щоб зупинити обробку повідомлення, можна використовувати спеціальне discard action:
    stop
    або
    ~
    в легасі-форматі.
  • Action часто використовуються шаблони. Шаблони дозволяють генерувати дані для передачі в Action з властивостей повідомлення, наприклад, формат повідомлення для передачі по мережі або ім'я файлу для запису. Детальніше про шаблони
  • Як правило, Action використовує модуль виводу("om...") або модуль зміни повідомлення("mm..."). Ось деякі з них:
    • omfile — виведення в файл

    • omfwd — пересилання по мережі, через udp або tcp
    • omrelp — пересилання по мережі за протоколом RELP
    • onmysql, ompgsql, omoracle — запис в базу
    • omelasticsearch запис ElasticSearch
    • omamqp1 — пересилка по протоколу AMQP 1.0
    • весь список модулів виводу
Детальніше про порядок обробки повідомлень.
Приклади конфігурації
Записуємо всі повідомлення категорій auth і authpriv в файл
/var/log/auth.log
, і продовжуємо їх обробку:
# legacy
auth,authpriv.* /var/log/auth.log
# новий формат
if ( $syslogfacility-text == "auth" or $syslogfacility-text == "authpriv" ) then {
action(type="omfile" file="/var/log/auth.log")
}

Усі повідомлення з ім'ям програми, що починається з "haproxy", записуємо в файл
/var/log/haproxy.log
, не скидаючи буфер на диск після запису кожного повідомлення, і припиняємо подальшу обробку:
# legacy (зверніть увагу на мінус перед іменем файлу, що відключає скидання буфера)
:programname, startswith, "haproxy", -/var/log/haproxy.log
& ~
# новий формат
if ( $programname startswith "haproxy" ) then {
action(type="omfile" file="/var/log/haproxy.log" flushOnTXEnd="off")
stop
}
# можна поєднувати
if $programname startswith "haproxy" then -/var/log/haproxy.log
&~

Перевірка конфига:
rsyslogd -N 1
. Більше прикладів конфігурації: раз, два.
Клієнт: пересилання логів із збереженням імені файлу
Зберігати імена файлів ми будемо в полі
TAG
. В імена хочеться включити каталоги, щоб не спостерігати однорівневу розсип файлів:
haproxy/error.log
. Якщо лог читається не з файла, а з переданих syslog повідомлень від програми, то вона може не погодитися записувати у TAG символ
/
, тому що це не відповідає стандарту. Тому ми можна закодувати їх подвійними підкресленнями, а на лог-сервері распарсим назад.
Створимо шаблон для передачі логів по мережі. Ми хочемо передавати повідомлення з тегами довше 32 символів(у нас довгі назви логів), і передавати більш точну, ніж стандартну, мітку часу із зазначенням тимчасової зони. Крім того, до назви лог-файла буде додано локальна змінна
$.suffix
, пізніше стане зрозуміло, навіщо. Локальні змінні в RainerScript починаються з крапки. Якщо змінна не визначена, вона розкриється в порожній рядок.
template (name="LongTagForwardFormat" type="string"
string="<%PRI%>%TIMESTAMP:::date-rfc3339% %HOSTNAME% %syslogtag%%$.suffix%%msg:::sp-if-no-1st-sp%%msg%")

Тепер створимо RuleSet, який буде використовуватися для передачі логів по мережі. Його можна буде приєднувати до Input, читає файли, або викликати функцію. Так, rsyslog дозволяє викликати один RuleSet з іншого. Для використання RELP треба спочатку завантажити відповідний модуль.
# http://www.rsyslog.com/doc/relp.html
module(load="omrelp")

ruleset(name="sendToLogserver") {
action(type="omrelp" Target="syslog.example.net" Port="20514" Template="LongTagForwardFormat")
}

Тепер створимо Input, читає лог-файл, і приєднаємо до нього цей RuleSet.
input(type="imfile"
File="/var/log/myapp/my.log"
Tag="myapp/my.log"
Ruleset="sendToLogserver")

Варто звернути увагу, що для кожного считываемого файлу rsyslog створює state-файли у своєму робочому каталозі(задається директивою
$WorkDirectory
). Якщо rsyslog не може створювати там файли, то весь лог-файл буде заново передаватися після перезапуску rsyslog.
У разі, якщо будь-який додаток пише в загальний syslog з визначеним тегом, і ми хочемо зберігати в файл, так і пересилати по мережі:
# Template to output only message
template(name="OnlyMsg" type="string" string="%msg:::drop-last-lf%\n")

if( $syslogtag == 'nginx__access:') then {
# write to file
action(type="omfile" file="/var/log/nginx/access" template="OnlyMsg")
# forward over network
call sendToLogserver
stop
}

Останній
stop
потрібен, щоб припинити обробляти ці повідомлення, інакше вони потраплять в загальний syslog. До речі, якщо додаток вміє вибирати інший unix socket для syslog, крім стандартного
/dev/log
(nginx і haproxy так вміють), то можна з допомогою модуля imuxsock зробити для цього сокета окремий Input і причепити до нього потрібний RuleSet, не розбираючи логи із загального потоку по тегам.

Читання лог-файлів, заданих через wildcard

Інтерлюдія
Програміст: Не можу знайти на лог-сервері логи somevendor.log за початок минулого місяця, подивися пліз
Девопс: Еее… а хіба ми пишемо такі логи? Попереджати ж треба. Ну в будь-якому випадку все старше тижня логротейт потер, якщо ми його не зберігали — значить вже немає.
Програміст: бурхливо обурюється
Якщо додаток пише багато різних логів, і іноді з'являються нові, то оновлювати конфіги кожен раз незручно. Хочеться це автоматизувати. Модуль imfile вміє зчитувати файли, задані вайлдкардом, і зберігати в мета-даних повідомлення шлях до файлу. Правда, шлях зберігається повний, а нам потрібен тільки останній компонент, який звідти доведеться добути. До речі, тут нам і знадобиться мінлива
$.suffix

input(type="imfile"
File="/srv/myapp/logs/*.log"
Tag="myapp__"
Ruleset="myapp_logs"
addMetadata="on")

ruleset(name="myapp_logs") {
# http://www.rsyslog.com/doc/v8-stable/rainerscript/functions.html
# re_extract(expr, re, match, submatch, no-found)
set $.suffix=re_extract($!metadata!filename, "(.*)/([^/]*)", 0, 2, "all.log");
call sendToLogserver
}

Вайлдкарды підтримуються тільки в режимі роботи imfile
inotify
(це режим за замовчуванням).

Багаторядкові повідомлення

Для роботи з лог-файлів, що містять багаторядкові повідомлення, модуль imfile пропонує три варіанти:
  • readMode=1
    — повідомлення розділені порожнім рядком
  • readMode=2
    — нові повідомлення починаються з початку рядка, продовження повідомлення йде з відступом. Часто так виглядають стектрейсы
  • startmsg.regex
    — визначати початок нового повідомлення regexp(POSIX Extended)
Перші два варіанти мають проблеми у режимі роботи
inotify
, і при необхідності третій легко їх замінює з відповідним regexp. Зчитування багаторядкових логів має одну тонкість. Зазвичай ознака нового повідомлення знаходиться в його початку, і ми не можемо бути впевнені, що програма закінчила писати минуле повідомлення, поки не почалося наступне. З-за цього останнє повідомлення може ніколи не передаватися. Щоб цього уникнути, ми задаємо
readTimeout
, після закінчення якого повідомлення вважається закінченим і буде передано.
input(type="imfile"
File="/var/log/mysql/mysql-slow.log"
# http://blog.gerhards.net/2013/09/imfile-multi-line-messages.html
startmsg.regex="^# Time: [0-9]{6}"
readTimeout="2"
# no need to escape new line for RELP
escapeLF="off"
Tag=" mysql__slow.log"
Ruleset="sendToLogserver")

Сервер
На сервері треба прийняти передані логи і розкласти їх по каталогах, відповідно до IP передавального хоста і часом отримання:
/srv/log/192.168.0.1/2017-02-06/myapp/my.log
. Для того, щоб задати ім'я лог-файла в залежності від змісту повідомлення, ми також можемо використовувати шаблони. Змінну
$.logpath
потрібно буде задати всередині RuleSet перед використанням шаблону.
template(name="RemoteLogSavePath" type="list") {
constant(value="/srv/log/")
property(name="fromhost-ip")
constant(value="/")
property(name="timegenerated" dateFormat="year")
constant(value="-")
property(name="timegenerated" dateFormat="month")
constant(value="-")
property(name="timegenerated" dateFormat="day")
constant(value="/")
property(name="$.logpath" )
}

Завантажимо потрібні модулі і вимкнемо
$EscapeControlCharactersOnReceive
, інакше в прийнятих логах всі переклади рядки заміняться на
\n

# Accept RELP messages from network
module(load="imrelp")
input(type="imrelp" port="20514" ruleset="RemoteLogProcess")

# Default parameters for file output. Old-style global settings are not working with new-style actions
module(load="builtin:omfile" FileOwner="syslog" FileGroup="adm" dirOwner="syslog"
dirGroup="adm" FileCreateMode="0640" DirCreateMode="0755")

# Module to remove 1st space message from
module(load="mmrm1stspace")

# http://www.rsyslog.com/doc/v8-stable/configuration/input_directives/rsconf1_escapecontrolcharactersonreceive.html
# Print recieved LF as-it-is not like '\n'. For multi-line messages
# Default: on
$EscapeControlCharactersOnReceive off

Тепер створимо RuleSet, разбирающий прилетіли логи і розкладає їх по папках. Служби, призначені для логування виключно на syslog, очікують, що він збереже час повідомлення. Тому логи, що прилетіли зі стандартними facility, ми будемо зберігати у форматі syslog, а для прилетіли з facility local0-local7 будемо виймати ім'я лода з поля
TAG
, і записувати тільки саме повідомлення без решти полів syslog. Проблема з приклеєним до повідомлення прогалиною залишається для RELP, тому що виникає ще на етапі розбору повідомлень, ми будемо цей пробіл відрізати.
Для збільшення продуктивності будемо писати асинхронно:
asyncWriting="on"
з великим буфером
ioBufferSize=64k
. Не будемо скидати буфер після кожного отриманого повідомлення
flushOnTXEnd="off"
, але будемо це робити кожну секунду, щоб логи з'являлися на лог-сервері досить оперативно:
flushInterval="1"
.
ruleset(name="RemoteLogProcess") {
# Facilities For local0-7 set log filename from $programname field: replace __ with /
# Message has arbitary format, syslog fields are not used
if ( $syslogfacility >= 16 ) then
{
# Remove 1st from space message. Syslog protocol legacy
action(type="mmrm1stspace")

set $.logpath = replace($programname, "__", "/");
action(type="omfile" dynaFileCacheSize="1024" dynaFile="RemoteLogSavePath" template="OnlyMsg"
flushOnTXEnd="off" asyncWriting="on" flushInterval="1" ioBufferSize="64k")

# Logs with filename defined from facility
# Message has syslog format, syslog fields are used
} else {
if (($syslogfacility == 0)) then {
set $.logpath = "-";
} else if (($syslogfacility == 4) or ($syslogfacility == 10)) then {
set $.logpath = "auth";
} else if (($syslogfacility == 9) or ($syslogfacility == 15)) then {
set $.logpath = "крок";
} else {
set $.logpath ="syslog";
}
# Built-in template RSYSLOG_FileFormat: High-precision timestamps and information timezone
action(type="omfile" dynaFileCacheSize="1024" dynaFile="RemoteLogSavePath" template="RSYSLOG_FileFormat"
flushOnTXEnd="off" asyncWriting="on" flushInterval="1" ioBufferSize="64k")
}
} # ruleset

Надійна доставка повідомлень. Черги
image
зображення з блогу k-max.name
Для деяких Actions виконання гальмувати або припинятися, наприклад пересилання логів по мережі або запису в базу. Щоб не втрачати повідомлення і не заважати працювати наступним Actions, черги. Кожному Action завжди зіставлена чергу повідомлень, за замовчуванням це Direct Queue нульового розміру. Ще є основна чергу для надійшли з усіх Input повідомлень, її теж можна налаштовувати.
Види черг: дискові, in-memory, і самий цікавий варіант — комбінований: Disk-Assisted Memory Queues. Такі черги використовують пам'ять і починають використовувати диск, якщо чергу в пам'яті переповнюється, або треба зберегти ненадіслані повідомлення на час перезавантаження сервісу. Повідомлення почнуть записуватися на диск, коли кількість повідомлень в черзі досягне
queue.highwatermark
, і пререстанут зберігатися на диск, коли їх кількість впаде до
queue.lowwatermark
. Щоб невідправлені зберігати повідомлення на диск під час презагрузки сервісу, треба вказати
queue.saveonshutdown="on"
.
Якщо персылка логів по мережі або запису в базу була неуспішною, Action призупиняється. rsyslog намагається відновити роботу Action через певні, що збільшуються з кожною спробою інтервали часу. Щоб логи почали пересилатися незабаром після вирішення проблем, треба виставити
action.resumeRetryCount="-1"
(необмежений) і інтервал для зупинки черзі поменше:
action.resumeInterval="10"
. Детальніше про параметри Actions.
RuleSet на клієнта з чергою буде виглядати так:
ruleset(name="sendToLogserver") {
# Queue: http://www.rsyslog.com/doc/v8-stable/concepts/queues.html#disk-assisted-memory-queues
# Disk-Assisted Memory Queue: queue.type="LinkedList" + queue.filename
# queue.size - max elements in memory
# queue.highwatermark - when to start saving to disk
# queue.lowwatermark - when to stop saving to disk
# queue.saveonshutdown - save on disk between rsyslog shutdown
# action.resumeRetryCount - number of retries for action, -1 = eternal
# action.resumeInterval - interval to suspend action if destination can not be connected
# After each 10 retries, the interval is extended: (numRetries / 10 + 1) * Action.ResumeInterval
action(type="omrelp" Target="syslog.example.net" Port="20514" Template="LongTagForwardFormat"
queue.type="LinkedList" queue.size="10000" queue.filename="q_sendToLogserver" queue.highwatermark="9000"
queue.lowwatermark="50" queue.maxdiskspace="500m" queue.saveonshutdown="on" action.resumeRetryCount="-1"
action.reportSuspension="on" action.reportSuspensionContinuation="on" action.resumeInterval="10")
}

Тепер можна спокійно перезугружать лог-сервер — повідомлення созраняться в черзі і будуть передані, коли він стане доступний.
Відмовостійкість
Можна налаштувати Action для виконання тільки у разі, якщо попереднє Action було призупинено: опис. Це дозволяє налаштовувати failover конфігурації. Деякі Actions використовують транзакції для збільшення продуктивності. У такому випадку успіх або невдача будуть відомі тільки після завершення транзакції, коли повідомлення вже оброблені. Це може призводити до втрати частини повідомлень без виклику failover Action. Щоб такого не відбувалося, треба ставити параметр
queue.dequeuebatchsize="1"
(за замовчуванням 16), що може знизити продуктивність.
ruleset(name="sendToLogserver") {
action(type="omrelp" Target="syslog1.example.net" Port="20514" Template="LongTagForwardFormat")
action(type="omrelp" Target="syslog2.example.net" Port="20514" Template="LongTagForwardFormat"
action.execOnlyWhenPreviousIsSuspended="on" queue.dequeuebatchsize="1")
}

Цю можливість я поки не пробував в продакшені.
Підсумок
Вийшла досить гнучка і зручна конфігурація. Логи передаються як файлів, так і з syslog. Багаторядкові повідомлення передаються коректно. Перезавантаження лог-сервера не викликає втрату даних. Для додавання нових логів достатньо оновити конфігурацію клієнта, сервер чіпати не треба.
Працює для rsyslog v8, на більш ранніх версіях не перевірялася. Для Ubuntu є офіційний ppa adiscon/v8-stable. Для CentOS/RHEL офіційний репозиторій.
p.s. Переклад цієї статті на англійську: https://selivan.github.io/2017/02/07/rsyslog-log-forward-save-filename-handle-multi-line-failover.html
Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.