Системы инициализации Unix и Linux после SysV

в 18:56, , рубрики: finit, openrc, systemd, sysvinit, upstart, Настройка Linux, системное администрирование, метки: , ,

До середины 2000-х никому в голову не приходило менять sysvinit, почти никому. Gentoo с самого начала создавала и развивала OpenRC. Все изменилось с появлением launchd в Mac OS X. Разработчики Ubuntu бросились создавать Upstart, в котором были позаимствованы некоторые идеи из launchd. Дело шло не шатко, не валко, но тут случился systemd и смешал все карты. Но кто же был истинным первопроходцем?

Системы инициализации Unix и Linux после SysV - 1

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, граница обведена красной прерывистой линией.

Системы инициализации Unix и Linux после SysV - 2

Теперь немного о принципах работы программы.

В самом начале системный инит запускает 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, умеет параллельно запускать и останавливать службы.

Использованные материалы

  1. Celebrating Daemontools
  2. Daemontools Intro
  3. Введение в Daemontools
  4. A history of modern init systems (1992-2015)

Автор: temujin

Источник

Поделиться

* - обязательные к заполнению поля