bash + logger варанты применения

Повседневные задачи администрирования Linux требуют автоматизации. Как правило, автоматизация сводится к написанию bash скриптов и их «ротации по крону», либо выполнении вручную, в зависимости от задачи. В этой заметке собраны часто встречающиеся практики логирования bash скриптов. Целевая аудитория — системные администраторы linux.

Самый простой и очевидный способ сохранить вывод скрипта это просто перенаправить его в файл.

exemple.sh > exemple.sh.log

На самом деле, нужно добавить к выводу STDERR, потому, как сообщения об ошибках пишутся именно в него:

exemple.sh > exemple.sh.log 2>&1


варинт
Как верно подметил Angel2S2
А еще лучше и проще делать так:
exemple.sh &>exemple.sh.log



Это считается нормальной практикой и обычно удовлетворяет большую часть системных администраторов. Но если серверов несколько(десятков, сотен), и логирование централизованно, удобнее использовать logger. Напомню, что logger это утилита, которая отправляет сообщения в syslog.

exemple.sh 2>&1 | logger 

Плюсы такого подхода в том, что можно перенаправлять вывод не только bash скриптов.

Минусы — невозможно отделить сообщения об ошибках от других информационных сообщений, так как в этом примере вывод слеплен в один поток и все это попадает в syslog с приоритетом user.notice(приоритет по умолчанию).

Для некоторых задач допустимо применение следующего варианта:

exemple.sh  2>&1 >/dev/null | logger -p user.error -t exemple.sh

В этом варианте логируется только STDERR (STDOUT перенаправляется в /dev/null) с приоритетом error. Также сообщения помечаются тегом с названием скрипта. Все это может упростить поиск и устранения неисправностей в работе скриптов.

Минусом этого подхода является то, что мы теряем STDOUT. Чтобы решить эту проблему можно использовать перенаправление потоков вывода непосредственно внутри скрипта.

#!/bin/bash

exec > >(logger  -p local0.notice -t `basename "$0"`) 
exec 2> >(logger  -p local0.error -t `basename "$0"`)

echo "error" >&2
echo "notice"


Этот пример иллюстрирует как можно перенаправить STDOUT и STDERR независимо друг от друга. К сожалению, этот способ порождает неожиданную проблему: сообщения из разных потоков могут попадать в syslog не в том порядке, в котором были отправлены. Такое поведение связано с тем, что потоки обрабатываются как два независимых друг от друга процесса. Не смотря на это, способ часто применяется для логирования скриптов, запускаемых cron.

Но иногда требуется запускать скрипт вручную, и в этом случае не всегда удобно следить за его работой в syslog.

#!/bin/bash
#
#                 .--------.
#                 | STDOUT |
#                 '--------'
#                      ^
#                      |
#   .--------.      .-----.     .--------.
#   | STDOUT |----->| tee |---->| logger |
#   '--------'      '-----'     '--------'
#

exec > >(tee >(logger  -p local0.notice -t `basename "$0"`))

# возможны варианты
exec 2> >(tee >&2 >(logger  -p local0.error -t `basename "$0"`))
#exec 2> >(logger  -p local0.error -t `basename "$0"` -s)


echo "error" >&2
echo "notice"

В этом примере tee копирует «входящий» поток в logger и обратно — в STDOUT(поведение по умолчанию), а во втором случае в STDERR. Таким образом мы получаем логирование в syslog + вывод на консоль во время выполнения, что бывает полезно для скриптов, запускаемых вручную.

Выводы:

Логи в syslog — это просто.
Логи в syslog — это полезно, особенно если логирование централизованно. При параллельном перенаправленнии потоков вывода — следует помнить о возможном нарушении порядка следования сообщений.

Ссылки по теме:

Redirecting bash script output to syslog
Logging From Launchd
  • +9
  • 19,3k
  • 7
Поделиться публикацией

Комментарии 7

    0
    Целевая аудитория — системные администраторы linux.

    А разве на Windows 10 (после летнего обновления) так делать нельзя будет?
    Ну и на Windows Server 2016.

    Я не разжигаю срач, мне просто для самообразования интересно, насколько широко можно bash будет применять в будущей серверной операционной системе.
    Я так же понимаю, что есть PowerShell, VBS, WMI. Но хочется знать конкретно про bash.

    Спрашиваю здесь в надежде, что специалисты по bash всё же не только Linux используют.
      0
      Если не ошибаюсь, logger входит в пакет rsyslog, поэтому, если запилят его под убунтой в Windows10, проблем не должно быть
        –1
        В Windows есть свой очень годный «рсуслог» с евентами и реакцией на прилетающие в логи евенты.
        Баш дается исключительно для удобства работы — так как администрировать win логичнее на его штатных средствах — а по мощи Powershell с его обьектами и всей дурью дотнета + использования удалённых powershell/wmi обьектов на других серверах стоит рядом по крутости с любом нормальным ЯП, вроде питона или руби, и со всей мощью 'ansible', впридачу.
        Писать на баше под винду можно, никто не запрещает, но это не торт для админства windows.
        Плюс стоит учитывать, что windows сервера кроме редких задач живут в core mode с минимумом вообще всего, кроме предустановленной на нём роли
        0

        Как вариант https://github.com/ildar-shaimordanov/bash.scripts/blob/master/bootstrap.sh. Там можно найти маленькое демо.

          0
          На самом деле, нужно добавить к выводу STDERR, потому, как сообщения об ошибках пишутся именно в него:

          exemple.sh 2&>1 > exemple.sh.log
          Не правильно. У вас идет вывод stdout в файл, а stderr попадет на stdout (к тому же опечатка, "&" должен идти после ">", а не перед), т.е. stderr в файл не попадет. Нужно делать наоборот, т.к. перенаправление «читается» справа налево:
          exemple.sh >exemple.sh.log 2>&1
          
          А еще лучше и проще делать так:
          exemple.sh &>exemple.sh.log
          
          тогда сразу и stderr и stdout пойдут в файл.

          Пояснение на примере
          $ (echo "stdout" ; echo "stderr" >&2 )
          stdout
          stderr
          $ (echo "stdout" ; echo "stderr" >&2 ) 2>&1 >/dev/null
          stderr
          $ (echo "stdout" ; echo "stderr" >&2 ) >/dev/null 2>&1
          $ (echo "stdout" ; echo "stderr" >&2 ) &>/dev/null



          Как-то truezemez разъяснял более подробно.
            +1
            Вы кончено, правы, благодарю за замечание. Исправил.
              0
              Не за что :)

          Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

          Самое читаемое