SysV, Upstart, systemd в роли ассортимента граблей Debian/Ubuntu

Знаете, чем я сейчас занимаюсь? Пишу стартовые скрипты для systemd, и это меня бесит.

Вроде бы как мы берем операционную систему для того, чтобы экономить время на таких вещах. Вроде как пакеты должны были облегчить нам жизнь. Весьма возможно, что мой выбор операционной системы был плох, но до сегодняшнего дня жить в области Debian/Ubuntu мне было вполне комфортно.

С другой стороны, «было» — это условность. Все мы часто находимся в относительном неведении относительно того, как устроена наша операционная система. А однажды увидев код /usr/sbin/service ты уже не можешь развидеть его. Так же как и пользоваться этим инструментом.

Наверное, нужно вернуться обратно. Чтобы понять, как мы оказались в такой заднице со смесью SysV и systemd, приправленной Upstart.

TL; DR: автор ноет по поводу зоопарка из SysV, Upstart и systemd в современных дистрибутивах Debian/Ubuntu.

SysV


Казалось бы, что может быть проще? В директории /etc/init.d/ находится файл с именем службы, он отвечает за запуск и остановку. Мы делаем /etc/init.d/service stop или /etc/init.d/service start и все работает отлично.

Операционная система делает то же самое, только в зависимости от runlevel, два — так два, буду последовательно выполнять симлинки из /etc/rc2.d, которые по сути своей ведут к /etc/init.d, жизнь проста и прекрасна. Чтобы управлять последовательностью достаточно изменить сортировку файлов при помощи числа. Есть утилиты, чтобы автоматизировать создание этих симлинков.

Почему мы не могли остаться в том месте? Потому что системы изменились. Они стали, гм, сложными.

Во-первых, состояние системы ранее было практически монолитным, а сегодня может быть изменчивым. Бах — и по USB подключили сетевой адаптер. При Томпсоне такого не было! Надо реагировать, т.е. уведомить службы об этом, кого-то перезапустить, кого-то запустить, кого-то погасить.

Во-вторых, SysV было глубоко плевать на интимную жизнь программ. Он их запускал на старте, но если у тебя что-то не получалось, то это был их личные проблемы. Отлаживать такие вещи, кстати, практически невозможно. Segmentation fault? Настоящие мужчины пишут программы, которые запускаются с первого раза и не сегфолтят, слабак.

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

В-четвертых, старт системы не мог быть параллельным. Запуск скриптов был строго последовательный. Это легко увидеть, если посмотреть на время старта OpenSUSE, например, лохматой 12 версии.

Правда, основная особенность SysV была не только в простоте. С простотой приходили проблемы. Например, если у меня каждый запуск скрипта start или stop отдельный, то как узнать, запущена программа или нет? Ведь ей нужно послать сигнал kill, а без PID его посылать некуда.

Свежей идеей было хранить эту цифру в файле .pid, прямо ну серьезно, свежей для своих далеких лет. Однако что делать, если программа вылетела с segmentation fault? Кратко: ничего, PID надо проверить, перед тем, как использовать.

Upstart


Мне кажется, что проблемы начались как раз тут. То есть, с того, как сообщество приняло Upstart. Это и задало дальнейший тон. Но по порядку.

Upstart поддерживал события. Он мог следить и перезапускать программы. Он умел выстраивать зависимости. Ну и с параллельностью у него тоже было все в порядке.

Кроме одной, огромной бочки дегтя, о которой я скажу дальше, я не помню никаких толком претензий к Upstart. А вот бочкой было то, что разработчики софта его в целом проигнорировали.

Почему? Я не знаю. Скорее всего потому, что совместимость с SysV была приоритетом для Upstart. Поэтому разработчикам ничего не нужно было менять.

В итоге, несмотря на то, что Upstart царствовал в Ubuntu 5 лет на протяжении с 2009 до 2014 года, огромное количество софта так и не перешло на него!

С одной стороны, я не могу винить в этом только разработчиков. Они, в конце концов, пишут программы. Как лучше запускать эти программы в системе — не их дело. Однако скрипты для SysV они пишут. Хотите примеров? Посмотрите, на что похож скрипт запуска postfix в Debian. Этот код монструозен, он ужасен, это же просто страшно.

Однако еще страшнее то, что многие администраторы вообще не видят и не понимают разницы. Они пишут:

sudo service apache2 start

И свято верят, что apache2 должен стартовать. Аргх, он не должен. Понимаете? Не должен. Запустится утилита /usr/bin/service, которая примется со страшной силой угадывать, как же нужно стартовать эту службу, а потом передаст вашу просьбу SysV или Upstart. Если сможет правильно угадать, ага.

service вообще не часть пакета Upstart. Оно вообще не оттуда, но как-то уживается в этом веселом кругу. Чтобы увеличить количество ада, некоторые разработчики делают скрипты /etc/init.d ссылающимися на Upstart. Эдакий уроборос, чтобы если вдруг администратор из лесу вышел и в Ubuntu 16.04 LTS напишет

/etc/init.d/service restart

Чтобы все работало.

Отдельно следует сказать про PID. Upstart не нужен PID в файле. Почему? Потому что любой запущенный им процесс остается его дочерним. Если вдруг он вылетит, то Upstart об этом узнает. И поскольку команды запуска и остановки тоже проходят через него, то тут нет никакой проблемы.

Однако как быть с сервисами, которым нужен fork? Ну для начала их надо спросить, зачем им это? Ведь в целом, fork применялся в основном для того, чтобы детачнуться от стартовавшего их процесса, но в случае с Upstart это делать незачем. Если у нас умер init, то у нас есть чуть больше проблем, чем неработающий postfix.

Да что уж там, сейчас, когда 16.04 LTS уже здесь, как думаете, при помощи чего стартует Apache2? postfix? Еще куча всякого? SysV.

Правда, в 16.04 им помогает systemd.

systemd


В целом, мне нравится systemd, честно. Его логика мне гораздо приятнее той, что была у Upstart. Правда, если бы еще Debian взяла бы не 215 релиз, а 218, то жить было бы еще лучше, но черт с ним, мы переживем и без команды edit, если надо.

И systemd можно долго ругать, но это уже стандарт. Однако как вы думаете, что делают разработчики с systemd? В основном игнорируют.

Итак, что привнес systemd? Генераторы! Тысячи их!

Кратко, если Upstart не выпендривался, а просто повторял поведение SysV, то systemd до такого не опускается. Он берет существующий /etc/init.d/service и на основе него генерирует скрипт для systemd. Его потом и запускает.

ExecStart=/etc/init.d/service start
ExecStop=/etc/init.d/service stop

Ну вот как бы да, вот примерно вот так оно и получается. Я не буду рассказывать о том, что это далеко не всегда работает так, как надо. Вернее, стартовать оно стартует. Не вздумайте в каком-нибудь продакшене положиться на рестарт такого сервиса, мониторинг станет вашим лучшим будильником.

И да, вы же понимаете, что systemd тем более не нужен PID, но увы. В сообществе это до сих пор остается толком не понятым.

К разработчикам


Да, ребята, я согласен, еще раз, запуск программы не есть ваша забота. Однако кто, как не вы, лучше знает, как спроектировать беспроблемный старт? Ведь одно дело, если команда старта выглядит так:

ExecStart=/usr/bin/control-bin start

А совсем другое, если так

ExecStart=/usr/sbin/postfwd2 --file=/etc/postfwd/postfwd.cf --interface=127.0.0.1 --port=10040 --shortlog --summary=600 --cache=600 --cache-rbl-timeout=3600 --cleanup-requests=1200 --cleanup-rbls=1800 --cleanup-rates=1200 --user=postfwd --group=postfwd

Давайте перестанем уже размазывать настройки между /etc/config.conf и /etc/default/service?

Давайте перестанем пытаться управлять стартом службы при помощи параметра START=yes в /etc/default/service? Нет, я понимаю, что «xyes» смотрится отличной шуткой, но надоело уже!

Давайте уже решим, что systemd — он везде. И что под него можно смело адаптироваться.

К самому себе


Смирись, тряпка, и не ной. Keep calm and systemd.

Комментарии (12)

  • 17 августа 2016 в 16:45

    +2

    Тем, кому кажется, что systemd просто, рекомендую посмотреть на современное устройство ceph. Там темплейты systemd дёргают триггеры upstart, которые инстансируют другие темплейты systemd, которые в свою очередь дёргают другие триггеры udev, которые, в свою очередь, дёргают systemd.

    отлаживать это — одно удовольствие.

  • 17 августа 2016 в 17:24

    0

    В защиту SysV хочу сказать, что он предельно прост и понятен широчайшим слоям пользователей. Даже полные ламеры, вроде меня, способны в кратчайшие сроки, при помощи гугла, форумов и старших товарищей слепить удобоваримый скрипт запуска демона. Более того, достаточно прозрачен механизм работы: просто посмотрев содержимое каталога, можно понять что и когда будет запущено. И контрольный в голову: этот скрипт из желудей и веток будет беспроблемно работать годами. А если перестанет, то его в состоянии будет починить практически любой, кто немного знаком с линуксом.
    В противовес же SysV, чтобы что-то настроить в systemd, нужно освоить мануал на 10 страниц, все эти юниты со своими конфигами и синтаксисом, этот systemctl с непонятными параметрами… я не админ, мне не нужна эта информация на каждый день (кстати, сдается мне что админам она тоже нужна далеко не каждый день), мне раз в пять лет надо настроить запуск демона и забыть про него. Средствами файловой системы это сделать много проще и понятнее.
    Вот лично для меня systemd не несет никаких удобств. Быть может поэтому его и многие другие игнорируют?
    • 17 августа 2016 в 17:27

      0

      Прочитайте внимательно. Бывает, что скрипты на SysV стартуют, однако приложение по какой-то причине вываливается на старте. Что делать? Я понимаю, запустить руками. Но без режима контроля и рестарта многие современные приложения тупо не работают нормально.

      Мануал на 10 страниц осваивать на надо. Не админу достаточно одну статью прочитать с базисом.

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

      • 17 августа 2016 в 17:46

        0

        Да я прочитал. Да, бывает. Правда, в моей практике приложения падали и при запуске скриптом и при запуске руками, так что все это достаточно просто диагностировалось. Видимо просто сложных случаев не было.
        Удобоваримый — это тот который, несмотря на всю свою кривизну, выполняет возложенные на него функции.
        Не админу достаточно одну статью прочитать с базисом.

        Эх, вашими бы устами… я вот сейчас почитал вводную статью, посмотрел примеры в своей системе. Понял что я по прежнему не имею представления в каком порядке все это запускается… понял что если вот прямо сейчас я немного уловил логику конструирования всего этого, то год спустя мне всю процедуру (включая чтение вводной статьи) придется начинать сначала.
        Вы в статье спрашивали почему все так держатся за SysV? Я ответил почему за него держусь я.
      • 17 августа 2016 в 17:46

        0

        Предположим приложение упало, что сделает systemd?
        Проанализирует ошибку с которой упало приложение и исправит или тупо перезапустит снова?
        • 17 августа 2016 в 17:54

          0

          Для начала, узнает, почему упало. Т.е. если его остановил админ, то перезапускать не надо.

          Если админ ничего не делал, а приложение ушло, то перезапустит. Приложение ведет лог, причем systemd помогает делать это в едином месте. Пусть админ потом разбирается, почему упало и что случилось.

          Поверьте, эта логика важна для критичных сервисов. Допустим стоит у вас postfix, в котором нашлась ошибка критическая, которая позволяет повалить его злоумышленнику. Его повалили ночью. Сработал мониторинг, вы пошли его перезапускать. С systemd он будет перезапущен без Вас.

          • 17 августа 2016 в 18:01

            0

            Предположим что это не postfix и что то случилось с данными на диске и сервис из за этого падает. А при старте он жрёт много процессорного времени и снова падает. В итоге из за systemd лежать весь сервер, да так гораздо лучше.

            А для падучих сервисов ну можно расписать скрипт который висит в памяти и сам перезапускает упавший сервис. Что в своё время я и делал для одного игрового сервиса.

            Я ничего против systemd не имею, но я им и не пользуюсь, однако усложнение системы старта когда не можешь найти, где, что и как стартует не радует.

  • 17 августа 2016 в 17:31

    0

    все сделано для людей…
  • 17 августа 2016 в 17:40

    0

    Всё, что я думаю о systemd в одной картинке — https://pbs.twimg.com/media/ChIcfpoXEAAPgFN.jpg
    • 17 августа 2016 в 17:43

      0

      Вы привели отличный пример уробороса. Автор пытается рестартовать службу при помощи /etc/init.d/service, что по сути работать не должно.

      Однако в системе кто-то об этом побеспокоился и сделал велосипед /etc/init.d/service → systemd, но что-то пошло не так, поскольку надо смотреть, как написан .service-файл.

      • 17 августа 2016 в 17:48 (комментарий был изменён)

        0

        > что по сути работать не должно.
        Вообще отношения к делу не имеет.

        root@libra:~# systemctl start rsync
        root@libra:~# echo $?
        0
        root@libra:~# telnet localhost 873
        Trying::1…
        Trying 127.0.0.1
        telnet: Unable to connect to remote host: Connection refused

        Полагаться на systemd нельзя. У него даже при несоблюдении ConditionPathExists «всё хорошо, я всё запустил, наслаждайтесь».
        Может идея-то в базе у systemd и хорошая, но написан он настолько коряво и настолько нелогично, что проще похоронить (что и случится лет через 5), чем тратить время на разбирательства.

        • 17 августа 2016 в 17:55

          0

          systemctl cat rsync в студию, покажите. Для начала разберемся, как оно запускается. Но /etc/init.d/service с systemd надо забыть.

© Habrahabr.ru