Daemontools




Copyright (C) 2003 М. Альхименко.
Оригинал статьи находится на http://lithium.opennet.ru
По всем вопросам обращайтесь на articles <at> lithium.opennet.ru

Любая публикация и перепечатка этого документа разрешается только с предварительного разрешения автора. При публикации запрещается каким-либо образом изменять содержимое документа.



Содержание:

Введение

      Как пишет сам DJB: "daemontools - это набор инструментов для управления UNIX-сервисами". Основными отличиями от обычных средств запуска (структуры каталогов rcx.d или rc.d или rc.local и пр.) является способность перезапускать сервис в случае его падения и наличие программы ведения и ротации логов (multilog). Преимущества первого отличия и так imho очевидны, а автоматическая ротация логов, кроме всего прочего, хороша тем, что не позволит исчерпать (случайно или умышленно) свободное место в разделе с /var/log/ разросшимися логами. Также, multilog позволяет вести лог вывода программ, не умеющих отдавать вывод в syslog. Таким образом, можно запускать как сервис программы, вообще не предназначенные для этого. Есть опыт использования этого пакета для запуска djbdns, qmail, squid и apache. Первый расчитан на работу именно в связке с daemontools, второй imho тоже был изначально рассчитан DJB для запуска через daemontools, хотя многие его запускают традиционным способом.

      Сразу следует уточнить: изложенное ниже - вольный перевод официального описания с http://cr.yp.to/daemontools.html, приправленое собственными комментариями. К тому же, не все удалось попробовать лично... Поэтому, ничто не заменит вам чтения оригинала документации.

      Все команды и пути даются из расчета на работу с RH-based Linux (RH9, ASP9), т.к. пока нет опыта работы с другим ОС. Если у вас другая система, и пути/команды не подходят, пишите — соответствующие поправки будут по возможности включены.

Установка

Создаем каталог /package:

# mkdir -p /package
# chmod 1755 /package
# cd /package

Скачиваем исходники daemontools-0.76.tar.gz в /package:

# wget http://cr.yp.to/daemontools/daemontools-0.76.tar.gz

(версия программы, как и её адрес со временем может поменяться)
Распаковываем:

# gunzip daemontools-0.76.tar
# tar -xpf daemontools-0.76.tar
# rm daemontools-0.76.tar
# cd admin/daemontools-0.76/src

Текущая версия daemotools, также как и qmail и djbdns, дает ошибку при сборке с версией glibc выше 2.3.1. Поэтому надо наложить патч, исправляющий эту несовместимость, если у вас она появляется. Сам патч можно найти на ftp://moni.csi.hu/pub/glibc-2.3.1/. Создаем папку для патча, скачиваем его туда и накладываем на исходники:

# mkdir patch
# cd patch
# wget ftp://moni.csi.hu/pub/glibc-2.3.1/daemontools-0.76.errno.patch
# cd..
# cd..
# patch -p1 < src/patch/daemontools-0.76.errno.patch

Собираем и устанавливаем пакет:

# package/install

После сборки и установки, программа svscanboot прописывается в inittab (SV:123456:respawn:/command/svscanboot) и демону init дается команда перечитать этот файл. Init запускает svscanboot (он теперь будет запускаться всегда при старте системы и перезапускаться, если он вдруг упадет (или вы его убьете сами)). Проверяем, все ли прошло удачно:

# pstree
...skip...
|-svscanboot-+-readproctitle
               `-svscan
...skip...
это обозначает, что svscanboot запущен и готов обслуживать сервисы.

Принцип работы

Теперь кратко о том, как все это работает. На запущенной системе дерево процессов, имеющих отношение к daemontools выглядит примерно так:

init-+
     |-svscanboot-+-readproctitle
     |            `-svscan-+-supervise---dnscache
     |                     |-supervise---multilog
     |                     |-supervise---qmail-send-+-qmail-clean
     |                     |                        |-qmail-lspawn
     |                     |                        |-qmail-rspawn
     |                     |                        `-splogger
     |                     |-supervise---tcpserver
     |                     |-supervise---splogger
     |                     `-supervise---squid-+-redirector
     |                                         |-10*[redirector]
     |                                         `-unlinkd

(лишние процессы вырезаны)

Svscanboot запускается при старте системы демоном init из inittab. Svscanboot запускает программу svscan в каталоге /service, который мы создали. В нем будут содержаться сведения о сервисах, которые daemontools будет контролировать - это подкаталоги, по одному для каждого сервиса. В случае падения svscanboot он перезапускается демоном init. Вывод запущенного svscan svscanboot перенаправляет в процесс readproctitle. Выглядит это так:
svscan /service2>&1 | readproctitle service errors: .....Далее следуют 400 точек, так что не пугайтесь, увидев их в выводе ps - так задумано. Последние 400 байт вывода svscan заменяют эти точки. Сделано это для того, чтобы можно было узнать о проблемах, запустив ps -auxww.

Svscan служит для запуска и слежения за сервисами. Он запускает по отдельному процессу supervise, который и будет контролировать сервис, для каждого обнаруженного каталога в /service (кроме тех, чьи имена начинаются с точки). Svscan каждые 5 секунд проверяет каталог /service на наличие новых подкаталогов. Если такие будут обнаружены, запускается новая копия supervise для каждого каталога. Если в подкаталоге сервиса содержится каталог log, то будет запущена еще одна копия supervise и создан pippeline между ними. Это сделано для использования логирования выводу программ минуя syslog - используя вывод программы из stdout и stderr. В daemontools для этих целей испольуется программа multilog - замена syslog от DJB, хоть и работает она по другим принципам. Так, например, dnscache из пакета djbdns выводит информацию о своей работе не в syslog, а в stdout. Этот вывод перенаправляется в multilog, который создает в своем подкаталоге main лог-файлы и осуществляет их ротацию. Также, svscan перенаправляет вывод всех дочерних supervise в readproctitle через pipeline, созданный svscanboot.

Supervise является процессом, непосредственно контролирующим сервис. Он вызывается с параметром, в котором содержится имя каталога для контролируемого сервиса в /service. В этом каталоге он ищет скрипт run, который и запускает. Если процесс, обслуживаемый supervise падает, supervise перезапускает его. Supervise создает в каталоге сервиса подкаталог supervise, в котором содержатся сведения о процессе. Эти сведения могут быть прочитаны с помощью программы svstat. Для управления сервисом служит программа svc.

Svc это средство для управления сервисами. Формат его вызова
svc opts services где opt - параметр, воздействующий на сервис, а services имя каталога сервиса, обслуживаемого supervice. Основные параметры, используемые с svc:

  • -u: Up. Если сервис не запущен, он запускается. Если сервис останавливается, он будет перезапущен.
  • -d: Down. Если сервис запущен, ему посылается сигнал TERM и затем сигнал CONT. После остановки, сервис не перезапускается.
  • -o: Once. Если сервис не запущен, он запускается. Если сервис останавливается, он не будет перезапущен.
  • -p: Pause. Посылает сервису сигнал STOP.
  • -c: Continue. Посылает сервису сигнал CONT.
  • -h: Hangup. Посылает сервису сигнал HUP.
  • -a: Alarm. Посылает сервису сигнал ALRM.
  • -i: Interrupt. Посылает сервису сигнал INT.
  • -t: Terminate. Посылает сервису сигнал TERM.
  • -k: Kill. Посылает сервису сигнал KILL.
  • -x: Exit. supervise завершит работу как только сервис завершится. Если вы используете этот параметр на стабильной системе, вы делаете что-то не так; supervise разработан, чтобы быть запущенным всегда.
(о сигналах в Unix читайте в man 7 signal).

Readproctitle запускается программой svcscanboot. При запуске svscan, его stderr и stdout перенаправляется в readproctitle. Вторым параметром его запуска являются некоторое количество точек (до 400). При получении на stdin какого-либо ввода, он выводит его вместо этих точек. Это позволяет сразу видеть ошибки при выводе списка процессов с помощью ps -auxww. (Опыт показывает, что это довольно полезная функция). Чтобы очистить cmdline процесса readproctitle после устранения ошибки можно запустить скрипт следующего содержания:

#!/bin/sh
echo -n \
> "service errors: \
............................................................\
(вырезано 18 одинаковых строк)
............................................................\
" > /proc/`pidof readproctitle`/fd/0

Этот скрипт посылает строку "service errors: " и 400 точек на stdin процесса через специальный файл в /proc. Можно просто создать исполняемый скрипт dots в /root/bin, т.к. этот путь обычно есть в PATH.

Multilog читает последовательность строк из stdin и добавляет выбранные строки в лог-файл. В качестве его параметров запуска выступают несколько операторов, каждый из них определяет действие, производимое с полученной строкой.
Каждая строка по умолчанию заносится в журнал.

Выбор:

Оператор
-шаблон исключает сроку, содержащую шаблон.
Оператор
+шаблон выбирает сроку, содержащую шаблон.
В этих правилах применяется символ подстановки "*".

Предупреждения:

Оператор e выводит первые 200 символов в stderr (которые, судя по всему, попадут в вывод readproctitle).

Файлы состояния:

Оператор =файл заменяет содержимое файл каждой выбранной строкой (первыми 1000 байтами).

Временные метки:

Оператор t добавляет в начало каждой строки символ @, точную временную метку (в формате TAI64) и пробел. Этот оператор должен быть первым. Перевести временную метку в удобочитаемую форму можно с помощью программы tai64nlocal.

Лог-файлы:

Если оператор каталог начинается с точки или слэша, то оператор каталог добавляет каждую выбранную строку в лог-файл в определенном каталоге (если каталог не существует, multilog его создаст). Ведение логов осуществляется следующим образом:
в каталоге содержится некоторое количество старых логов, лог с именем current (текущий лог), и другие файлы, с помощью которых multilog отслеживает свои действия. Имя каждого лога начинается с @, продолжается временной меткой, обозначающей, когда запись в лог была завершена и завершается следующими символами:

  • s: Файл полностью завершен и нормально записан на диск.
  • u: Запись в файл была завершена некорректно и он может быть усечен. Этот файл не был обработан с помощью оператора !processor
Оператор
sразмер является максимальным размером файла для последующего оператора каталог. Когда current достигает этого размера multilog начинает новый файл. Размер должен быть между 4096 и 16777215 байт. Размер по умолчанию - 99999 байт.
Оператор nколичество определяет максимально количество лог-файлов для последующего оператора каталог. Этот параметр должен быть не меньше 2. Значение по умолчанию - 10. При переименовании файла current multilog удаляет самый старый лог-файл в каталоге, если их количество равно или больше значения этого оператора.
Оператор !processor определяет processor (программу-обработчик) для последующего оператора каталог. Этой программе будет передан файл current на stdin перед перед началом нового файла. Вывод программы сохраняется в старом файле current, после чего он переименовывается и создается новый файл current.


Остальные программы

Здесь описаны основные программы из состава daemontools, но не все. С назначением остальных можно ознакомиться на http://cr.yp.to/daemontools.html. Вот их краткое описание:
  • svok - проверяет, запущен ли определенный сервис. Ничего не выводит на stdout и stderr, результат проверки представлен в виде кода завершения.
  • svstat - сообщает, запущен ли определенный сервис и выводит некоторую информацию о его работе.
  • fghack - не позволяет уйти сервису в фоновый режим. Используется для запуска демонов, не способных работать в no-daemon mode.
  • tai64n - добавляет timestamp в формате TAI64 к каждой полученной строке.
  • tai64nlocal - переводит timestamp из формата TAI64 в удобочитаемую форму.
  • setuidgid - запускает программу под определенными uid и gid.
  • envuidgid - запускает программу с переменными окружения, указывающими на определенные uid и gid ($UID и $GID).
  • envdir - запускает программу с измененными переменными окружения, полученными из файлов в определенном каталоге.
  • softlimit - запускает программу с новыми ограничениями ресурсов.
  • Что делает pgrphack и зачем нужна setlock — так и осталось неясным. Предоставляю вам разобраться в этом самим и написать автору ;) .


Сcылки: