Регистрация выхода демона с помощью Upstart

34

У меня есть пользовательский демон, которым управляет upstart на моем сервере Ubuntu. Он работает отлично, за исключением того, что мне нужно захватить (зарегистрировать) выходные данные демона. На официальной странице разделов сказано, что я могу использовать console loggedдля этого, но в какой файл он входит?

Я также читал , что console loggedэто больше не является допустимой строфа . В настоящее время я использую 0.3.9 (Hardy), но через несколько месяцев обновлюсь до 0.6.x (Lucid). Если console loggedна самом деле не будет работать с более поздними версиями, что я буду использовать вместо этого?

Алекс Рейснер
источник
1
Можете ли вы просто обновить свой пользовательский демон для отправки вывода в системный журнал или в файл журнала, указанный в файле конфигурации демона?
Зоредаче

Ответы:

35

Этот фрагмент перенаправит вывод вашей службы в регистратор, но при этом позволит вам выполнить процесс службы (таким образом, заменив процесс оболочки), чтобы upstart не запутался. Это также гарантирует, что процесс логгера перезапускается в init, так что он не является дочерним элементом вашего сервиса, и он избегает бесполезного использования файловой системы, даже если ему необходимо временно создать fifo.

script
  mkfifo /tmp/myservice-log-fifo
  ( logger -t myservice </tmp/myservice-log-fifo & )
  exec >/tmp/myservice-log-fifo
  rm /tmp/myservice-log-fifo
  exec myservice 2>/dev/null
end script

Вот как это работает:

  1. mkfifo /tmp/myservice-log-fifoпросто делает специальный файл fifo (он же именованный канал). Введите man 7 fifoдля получения дополнительной информации.
  2. ( logger ... </tmp/myservice-log-fifo & ) начинает чтение логгера с fifo, в фоновом режиме. Парены приводят к тому, что процесс регистратора переопределяется в init, а не остается дочерним процессом текущего процесса оболочки.
  3. exec >/tmp/myservice-log-fifoперенаправляет стандартный вывод текущей оболочки на fifo. Теперь у нас есть открытый файловый дескриптор для fifo, и нам больше не нужна запись в файловой системе ...
  4. rm /tmp/myservice-log-fifo поэтому мы удалим это.
  5. exec myservice 2>/dev/nullпросто запускает сервис обычным способом. Stdout уже идет на fifo, и это не изменится, когда новая программа будет выполнена.

UPDATE: set -e не требуется, так как Upstart по умолчанию запускает сценарии с этой опцией (см. Http://upstart.ubuntu.com/cookbook/#develop-scripts-using-bin-sh ).

Кит Рэрик
источник
отличный ответ, и не оставляет файлов fifo где-либо валяться.
Эш Берлин-Тейлор
Что это set -e?
Питер Маунс
1
Это set -eприводит к немедленному завершению работы сценария в случае сбоя какой-либо команды. Без этой строки скрипт продолжит бесполезный запуск последующих команд (и, возможно, опасно).
Кит Рарик
1
Чтобы зарегистрировать как stderr, так и stdout, добавьте строку exec 2>&1над rmстрокой и удалите ее 2>/dev/nullиз последней строки.
егоadok
31

Для последних версий Ubuntu (12.04+) просто используйте

console log

И вывод демона (STDOUT & STDERR) будет добавлен к /var/log/upstart/<service>.log

http://upstart.ubuntu.com/cookbook/#console-log

Willem
источник
2
Это было бы чисто и хорошо, но, к сожалению, он не работает на CentOS 6.x, который все еще выпускает древнюю версию выскочки, которая не поддерживает это.
Кристиан Магерушан-Станчу
11

Если вы используете console output раздел , а затем перенаправляете выходные данные вашего скрипта в logger(командный интерфейс оболочки в модуль системного журнала syslog (3)), это будет работать.

Например

console output
exec /my/script | logger

войдет в /var/log/messages

Например

console output
exec /my/script | logger -t my-script

войдет в систему /var/log/messagesи пометит каждое сообщениеmy-script

logger --help для вариантов использования регистратора.

(Я использую Amazon Linux AMI, который основан на Centos 5.x; YMMV)

Питер Мунс
источник
4
Оказывается, это не очень хорошее решение. upstart защелкивается на PID logger, а не на процесс, которым вы действительно хотите управлять.
Питер Маунс
10

Я не заставил mkfifoтрюк работать удовлетворительно; казалось, что он не захватывает stderr, и попытки перенаправить вынудили Upstart выполнить без ошибок.

У него также есть неприятный побочный эффект, заставляющий loggerпроцесс зависать как потомок init, поэтому информация о том, кто «владеет» регистратором, теряется, и любой, кто еще не знает об этом, mkfifoможет предположить, что это зависший процесс, который можно убить.

Вместо этого я получил следующее решение, которое решает все эти проблемы. Он logger становится дочерним процессом, сохраняя службу в качестве корневого процесса. К сожалению, это требует исполнения bash, но выглядит просто грязно.

script
  # ... setup commands here, e.g. environment, cd, ...
  exec bash <<EOT
    exec 1> >(logger -t myservice) 2>&1
    exec myservice
EOT
end script

Это использует трюк, который перенаправляет stdout и stderr в команду. Поскольку мы выполняем службу внутри bashкоманды, это побочный эффект - замена оболочки и магическое превращение bash в дочерний процесс службы, как показано ps aufxw:

myservice 
 \_ bash -c exec 1> >(logger -t myservice) 2>&1 && exec myservice
    \_ logger -t myservice

По какой-то причине вышеупомянутая команда должна быть заключена в bash -c. Я предполагаю, что это потому, что Upstart только делает вид, что запускает ваш скрипт через Bash, но на самом деле это не так. Если кто-нибудь может предложить способ избежать дополнительной оболочки bash, это было бы здорово.

Александр Стаубо
источник
1
Да! Я так рад, что нашел это. Выглядит лучше, чем вариант mkfifo, и в моем случае мне нужно было, exec bash -l << EOFчтобы без потерь.
thom_nic
6

Это уродливо, но пока лучшее, что я нашел

exec / path / to / server >> /tmp/upstart.log 2> & 1

Хорхе Варгас
источник
2
Решение не является хорошим, когда дело доходит до ротации журналов, потому что приложение ведет журнал непосредственно в файл. Регистрация через системный журнал позволяет избежать связанных с этим проблем.
Марк Стосберг
3

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

exec $SERVER 2>&1 | logger -t myservice -p local0.info

Однако конвейер может привести к тому, что программа upstart перепутает PID процесса регистрации с PID демона.

Nikratio
источник
Демон, сбивающий с толку PID, на самом деле является бесполезным демоном, так как он должен наблюдать за процессом, затем возродить его. Любая идея о том, как убедиться, что правильный PID отслеживается?
Иоганн Филипп Стратхаузен
Я думаю (но не пытался), что вы хотите expect forkили expect daemonстрофа. Или cat, я думаю, вы могли бы добавить pid-файл в сообщение журнала.
Питер Маунс
1

Другой альтернативой является использование тройника, как:

exec $SERVER 2>&1 | tee /dev/stderr | logger -t myservice

чтобы получить как файл upstart, так и вывод syslog

Perl
источник