До середины 2000-х никому в голову не приходило менять sysvinit, почти никому. Gentoo с самого начала создавала и развивала OpenRC. Все изменилось с появлением launchd в Mac OS X. Разработчики Ubuntu бросились создавать Upstart, в котором были позаимствованы некоторые идеи из launchd
. Дело шло не шатко, не валко, но тут случился systemd и смешал все карты. Но кто же был истинным первопроходцем?
Daniel J. Bernstein математик и специалист по криптографии, автор популярного MTA qmail и множества других менее известных программ, среди которых выделяется daemontools. Для множества современных систем инициализации daemontools являлся примером и вдохновителем. Прошу внутрь для того, чтобы познакомиться с самой элегантной, простой и влиятельной системой управления службами в Unix / Linux.
DJB и Daemontools
Уравнения Максвелла для управления процессами на Unix ОС.
Внимание — не следует путать daemontools написанный DJB с программой-тезкой DAEMON Tools для монтирования iso образов и создания виртуальных CD/DVD дисков.
Daniel J. Bernstein создал свою программу в 1997 г. Последний стабильный релиз был в июле 2001 г.
Сейчас, когда в Linux сообществе наблюдается раскол из-за systemd, самое время вспомнить каким может быть настоящий инит в духе принципов и философии Unix. В этом смысле дзен-программист DJB является воплощением минимализма и простоты, а бритва Оккама у него встроена в клавиатуру. Его решения основательны и элегантны, на этом фундаменте он строит надежное, безопасное ПО, которое потребляет минимальное количество ресурсов ОС. Вот некоторые особенности его стиля работы.
- Самый большой файс исходного кода
multilog.c
имеет всего лишь 13898, нет не строк, а байтов. Командаwc
указывает лишь на 617 строк кода. - Большинство функций имеют меньше 30 строк.
- Принцип — никогда ничего не парсить.
- Принцип — использовать все, что дает ОС и не изобретать велосипеды.
Почему такие странные принципы, и еще с учетом того, что автор исповедует их фанатично? Строительный материал daemontools — директории, процессы, FIFO, исполняемые файлы. Это дает массу преимуществ в разработке и отладке приложения:
- Тестировать запуск службы проще простого — если запустится исполняемый файл
./run
, то и служба тоже запустится. - Можно использовать любой язык программирования, не только Bash. Сгодится даже скомпилированный бинарник.
- Понятно, что и как делает программа даже без подробного прочтения документации и изучения исходного кода.
- Парсить разнообразные текстовые структуры — на удивление трудная задача, если это делать по уму. Автор избегает этого, умело используя иерархическое свойство файловой системы Unix для воссоздания структуры переменных среды
ключ=значение
.
Сравнительная таблица DT
Стоит обратить внимание на неортодоксальную структуру директорий daemontools, ничтоже сумняшеся программа создает каталоги в корне файловой системы Unix. DJB прописал в коде программы директории/service
, /command
и рекомендует создать /package
для исходников программы. Это считается весьма дурным тоном в Unix и Linux, создатели дистрибутивов всеми силами избегают этого, также как и пользователи с правами root.
features | inittab | ttys | init.d | rc.local | /service |
---|---|---|---|---|---|
Easy service installation and removal | No | No | Yes | No | Yes |
Easy first-time service startup | No | No | No | No | Yes |
Reliable restarts | Yes | Yes | No | No | Yes |
Easy, reliable signalling | No | No | No | No | Yes |
Clean process state | Yes | Yes | No | No | Yes |
Portability | No | No | No | No | Yes |
Давайте пробежимся по таблице самовосхваления daemontools. Начнем с первой строчки. Действительно создание и удаление нового сервиса проще простого, добавил, или удалил новую директорию в /service
вместе с файлом ./run
и на этом все. Сравните со скриптами sysvinit и остальных инитов, чтобы оценить простоту такого способа достичь того же самого.
Второй пункт менее убедителен в том смысле, что конечно же проще когда сервис и в первый раз стартует автоматически, но в остальных системах инициализации и управления службами достаточно одной команды для первого старта службы.
Возможность перезапустить завершившийся сервис в автоматическом режиме была на тот момент момент большим шагом вперед. На сегодняшний день это уже в порядке вещей.
Четвертая позиция — сигналы. Команда svc
, как показано ниже, позволяет послать службе практически любой сигнал POSIX стандартов.
Последние две позиции кажутся несколько надуманными, не совсем понятно как daemontools восстанавливает состояние процесса в отличие от остальных инитов. Непонятно также, почему автор только свою программу считает переносимой на другие платформы.
Структура DT
По словам автора: daemontools — это набор инструментов для управления службами UNIX. Основными отличиями от традиционных инитов (структуры директорий rcX.d, rc.d, rc.local и пр.) является способность перезапустить сервис в случае его падения и наличие программы ведения и ротации логов — multilog. Также, multilog позволяет вести лог вывода программ, не умеющих перенаправлять вывод в syslog
. Таким образом, можно запускать как сервис программы, для этого вовсе не предназначенные.
Внутреннее устройство daemontools, граница обведена красной прерывистой линией.
Теперь немного о принципах работы программы.
В самом начале системный инит запускает svscanboot
, который затем запускает программу svscan
в ново-созданной директории svscan
. Далее svscanboot
перенаправляет вывод запущенного svscan
в отладочный процесс readproctitle
.
Ядром daemontools являются всего две программы: svscan
и supervise
. Первая запускается с единственным аргументом по выбору, а вторая — с обязательным ключом.
Svscan служит для запуска и слежения за сервисами. Каждые 5 секунд Svscan
проверяет каталог /service
, если другой не задан, на наличие новых подкаталогов. Если такие будут обнаружены, запускается новая копия supervise
для каждого каталога.
Supervise является, в соответствии с названием, контролирующем процессом. Он вызывается с параметром, в котором содержится имя каталога и в нем ищет скрипт ./run
, который и запускает. Если по каким-то причинам ./run
перестал исполняться, то тогда supervise
его перезапустит после небольшой паузы — чтобы не создавать дополнительной нагрузки на ОС. Supervise
не перезапустит ./run
, если в каталоге будет обнаружен файл ./down
. Supervise
создает в каталоге сервиса подкаталог ./supervise
, в котором хранятся данные о процессе. Эти данные могут быть прочитаны с помощью утилиты svstat
. Для управления сервисом служит программа svc
.
Синтаксис команды svc
и опции представлены ниже.
svc options services
- -u: Up, запустить сервис, в случае останова — перезапустить.
- -d: Down, остановить сервис.
- -t: Terminate, посылает сервису сигнал TERM.
- -k: Kill, посылает сервису сигнал KILL.
- -p: Pause, посылает сервису сигнал STOP.
- -c: Continue, посылает сервису сигнал CONT.
- -h: Hangup, посылает сервису сигнал HUP.
- -a: Alarm, посылает сервису сигнал ALRM.
- -h: Interrupt, посылает сервису сигнал INT.
- -x: Exit,
supervise
завершит работу как только./run
или его потомок завершится. - -o: Once, запустить сервис, но не перезапускать после его завершения.
Есть еще одно обстоятельство, если в рабочем каталоге supervise
содержится подкаталог ./log
, в котором есть ./log/run
, то тогда будет запущена еще одна копия supervise
и создан канал между ./run
и ./log/run
.
Попробуем добавить сервис sshd.
#!/bin/sh
# перенаправить stderr в stdout
exec 2>&1
# с опцией -D sshd выполняется явно, с опцией -e отладка пишется в stderr
exec /usr/sbin/sshd -D -e
В таком случае структура директорий может выглядеть так.
- service/
|- ngetty/
| |- run
| |- log/
| |- run
|- sshd/
| |- run
| |- log/
| |- run
|- squid/
| |- run
| |- log/
| |- run
После того, как svscan
пробежится по этому списку мы получим дерево процессов, в котором процессы service
следят за сервисами и логированием.
-svscan-+-service-+-ngetty
| `-log-service
+-service-+-sshd
| `-log-service
+-service-+-crond
| `-log-service
Зависимости между службами
Несмотря на то, что программа не поддерживает зависимости между различными службами, есть способ добиться учета зависимостей, используя для этого svok
следующим образом.
#!/bin/sh
svok postgres || (echo "waiting for postgres..." && exit 1)
exec 2>&1
exec python3 your-web-app.py
- svok — проверяет, запущена ли определенная служба. Ничего не выводит в
stdout
иstderr
, если служба запущена, то тогда программа возвращает код 0, в противном случае — код 100.
В данном примере программа на python запустится только в том случае, если стартовал postgres, если же последний пока не поднялся, скрипт завершится и затем через определенно время svscan
его перезапустит. Когда же postgres наконец поднимется, python запустит веб приложение.
Квотирование сервиса
С помощью утилиты softlimit
можно ограничить предоставленные данному сервису ресурсы.
#!/bin/sh
exec 2>&1
# сменить пользователя на foo, ограничить стек 4096 байтами, открытые
# файловые дескрипторы 15 и количество процессов 1:
exec setuidgid foo softlimit -n 4096 -o 15 -p 1
bar -n
- softlimit — запускает программу с ресурсными ограничениями.
Логирование
Если у вас есть некая программа foo
, которая не ведет логов, вы без труда сделаете это с помощью multilog
, собрав в отдельном файле вывод stdout
и stderr
с временными метками.
[root@home: +5] cd /service/foo && mkdir log
[root@home: +5] cd log && mkdir mail
[root@home: +5] nano run.new #пишем в файл
#!/bin/sh
exec 2>&1
exec multilog t ./main
[root@home: +5] chmod u+x run.new
[root@home: +5] mv run.new run
[root@home: +5] cd /service
[root@home: +5] svc -t foo
Из другого терминала запускаем:
tail -fn0 /service/foo/main/current
Последователи daemontools
Мало кто сегодня использует DT, но можно смело сказать, что Daniel J. Bernstein стал для многих примером, а дело его живет и здравствует. Вот неполный список его последователей.
- daemontools-encore — Разработчик Bruce Guenter, является дальнейшим развитием DT. Не полноценный инит, также как и оригинал.
- runit — Разработчик Gerrit Pape, умеет параллельно запускать службы. Хабрапост.
- s6 — Полноценный асинхронный инит с PID 1.
- nosh — Легковесный гипервизор процессов для BSD и Linux, умеет параллельно запускать и останавливать службы.
Использованные материалы
- Celebrating Daemontools
- Daemontools Intro
- Введение в Daemontools
- A history of modern init systems (1992-2015)
Автор: temujin