История изменений
Исправление siraenuhlaalu, (текущая версия) :
Основное отличие systemd от sysvinit и openrc в том, что там нет костыля с pid-файлами. Суть в чём: когда мы стартуем сервис, мы запускаем бэш-скрипт, который, в свою очередь стартует процесс в бэкграундном режиме, закрыв его stdin/err/out и выходит. Из системы инициализации при этом раскладе мы не можем вытащить PID демонизированного процесса, поэтому мы вынуждены придумывать костыли, допустим, сервис, должен писать в /var/run/apache2.pid свой PID и только тогда в /etc/init.d/apache2 status мы сможем получить этот PID и через ps вытащить, жив ли процесс. Если по какой-то причине есть проблемы с локфайлом, поведение sysvinit скриптов будет неопределённым. Или же разработчики сервиса должны сделать свою утилиту по типу apachectl, которая пишет в сокет для управления сервисом и получает оттуда статус. Абсолютно аналогичная ситуация с cron: если тебе нужно обеспечить, к примеру, запуск только одной задачи за раз (допустим, время выполнения может быть больше интервала, указанного в crontab), тебе придётся делать костыли с flock или реализовывать ненужную логику в коде. В systemd же мы можем в явном виде отследить все дочерние процессы и запускать второй инстанц только после завершения первого.
Второе отличие следует из первого: поскольку мы не закрываем дескрипторы запущенных сервисов, мы можем получить их логи в одном месте. То есть разработчику сервиса достаточно писать в stdout/err, вместо явной реализации логгирования в файл в коде процесса или сервиса.
Третье отличие (в большей степени от sysvinit): там меньше копипаста. Можно взять любой скрипт от sysv-сервиса и там обязательно будет что-то вроде: source /etc/default/servicename
[ -Z $PIDFILE ] && PIDFILE=/var/run/servicename.pid
start(){
/sbin/servicename –pidfile $PIDFILE –daemonize
}
case $1 in
start)
start
;;
stop)
stop
;;
esac
Ну и из минусов: был переходный период, когда было непонятно, какой системой запускается тот или иной сервис, итого утилиты от systemd использовали врапперы для sysvinit-сервисов и наоборот, что приводило к аду с точки зрения дебаггинга, когда что-то не работает или имеет неправильные зависимости. Сейчас это в принципе пофикшено и должно работать в современных дистрибутивах нормально.
Вторая проблема это то, что если для старта сервиса нужно реализовывать какую-то хитрую логику, начинается веселье. Допустим, есть сервис, у которого конфиг лежит в /etc/default/servicename и если конфига нет или пустой, сервис не должен стартовать, для этого делается отдельная опция из серии: AssertFileNotEmpty=/etc/default/servicename , или нужно удалить временные файлы перед стартом: ExecStartPre=/bin/rm -fr /blabla . И такая опция есть для каждого из 666 случаев.
Исправление siraenuhlaalu, :
Основное отличие systemd от sysvinit и openrc в том, что там нет костыля с pid-файлами. Суть в чём: когда мы стартуем сервис, мы запускаем бэш-скрипт, который, в свою очередь стартует процесс в бэкграундном режиме, закрыв его stdin/err/out и выходит. Из системы инициализации при этом раскладе мы не можем вытащить PID демонизированного процесса, поэтому мы вынуждены придумывать костыли, допустим, сервис, должен писать в /var/run/apache2.pid свой PID и только тогда в /etc/init.d/apache2 status мы сможем получить этот PID и через ps вытащить, жив ли процесс. Если по какой-то причине есть проблемы с локфайлом, поведение sysvinit скриптов будет неопределённым. Или же разработчики сервиса должны сделать свою утилиту по типу apachectl, которая пишет в сокет для управления сервисом и получает оттуда статус. Абсолютно аналогичная ситуация с cron: если тебе нужно обеспечить, к примеру, запуск только одной задачи за раз (допустим, время выполнения может быть больше интервала, указанного в crontab), тебе придётся делать костыли с flock или реализовывать ненужную логику в коде. В systemd же мы можем в явном виде отследить все дочерние процессы и запускать второй инстанц только после завершения первого.
Второе отличие следует из первого: поскольку мы не закрываем дескрипторы запущенных сервисов, мы можем получить их логи в одном месте. То есть разработчику сервиса достаточно писать в stdout/err, вместо явной реализации логгирования в файл в коде процесса или сервиса.
Третье отличие (в большей степени от sysvinit): там меньше копипаста. Можно взять любой скрипт от sysv-сервиса и там обязательно будет что-то вроде: source /etc/default/servicename
[ -Z $PIDFILE ] && PIDFILE=/var/run/servicename.pid
start(){
/sbin/servicename –pidfile $PIDFILE –daemonize
}
case $1 in
start)
start
;;
stop)
stop
;;
esac
Ну и из минусов: был переходный период, когда было непонятно, какой системой запускается тот или иной сервис, итого утилиты от systemd использовали врапперы для sysvinit-сервисов и наоборот, что приводило к аду с точки зрения дебаггинга, когда что-то не работает или имеет неправильные зависимости. Сейчас это в принципе пофикшено и должно работать в современных дистрибутивах нормально.
Вторая проблема это то, что если для старта сервиса нужно реализовывать какую-то хитрую логику, начинается веселье. Допустим, есть сервис, у которого конфиг лежит в /etc/default/servicename и если конфига нет или пустой, сервис не должен стартовать, для этого делается отдельная опция из серии: AssertFileNotEmpty=/etc/default/servicename или нужно удалить временные файлы перед стартом: ExecStartPre=/bin/rm -fr /blabla И такая опция есть для каждого из 666 случаев.
Исходная версия siraenuhlaalu, :
Основное отличие systemd от sysvinit и openrc в том, что там нет костыля с pid-файлами. Суть в чём: когда мы стартуем сервис, мы запускаем бэш-скрипт, который, в свою очередь стартует процесс в бэкграундном режиме, закрыв его stdin/err/out и выходит. Из системы инициализации при этом раскладе мы не можем вытащить PID демонизированного процесса, поэтому мы вынуждены придумывать костыли, допустим, сервис, должен писать в /var/run/apache2.pid свой PID и только тогда в /etc/init.d/apache2 status мы сможем получить этот PID и через ps вытащить, жив ли процесс. Если по какой-то причине есть проблемы с локфайлом, поведение sysvinit скриптов будет неопределённым. Или же разработчики сервиса должны сделать свою утилиту по типу apachectl, которая пишет в сокет для управления сервисом и получает оттуда статус. Абсолютно аналогичная ситуация с cron: если тебе нужно обеспечить, к примеру, запуск только одной задачи за раз (допустим, время выполнения может быть больше интервала, указанного в crontab), тебе придётся делать костыли с flock или реализовывать ненужную логику в коде. В systemd же мы можем в явном виде отследить все дочерние процессы и запускать второй инстанц только после завершения первого.
Второе отличие следует из первого: поскольку мы не закрываем дескрипторы запущенных сервисов, мы можем получить их логи в одном месте. То есть разработчику сервиса достаточно писать в stdout/err, вместо явной реализации логгирования в файл в коде процесса или сервиса.
Третье отличие (в большей степени от sysvinit): там меньше копипаста. Можно взять любой скрипт от sysv-сервиса и там обязательно будет что-то вроде: source /etc/default/servicename [ -Z $PIDFILE ] && PIDFILE=/var/run/servicename.pid start(){ /sbin/servicename –pidfile $PIDFILE –daemonize } case $1 in start) start ;; stop) stop ;; esac
Ну и из минусов: был переходный период, когда было непонятно, какой системой запускается тот или иной сервис, итого утилиты от systemd использовали врапперы для sysvinit-сервисов и наоборот, что приводило к аду с точки зрения дебаггинга, когда что-то не работает или имеет неправильные зависимости. Сейчас это в принципе пофикшено и должно работать в современных дистрибутивах нормально.
Вторая проблема это то, что если для старта сервиса нужно реализовывать какую-то хитрую логику, начинается веселье. Допустим, есть сервис, у которого конфиг лежит в /etc/default/servicename и если конфига нет или пустой, сервис не должен стартовать, для этого делается отдельная опция из серии: AssertFileNotEmpty=/etc/default/servicename или нужно удалить временные файлы перед стартом: ExecStartPre=/bin/rm -fr /blabla И такая опция есть для каждого из 666 случаев.