суббота, 30 июня 2012 г.

systemd для администраторов, часть 4

Это перевод четвертой статьи из серии "systemd for Administrators". В этой части описан процесс убийства служб с помощью systemd.
Автор оригинала: Леннарт Поттеринг (Lennart Poettering).
Ссылка: http://0pointer.de/blog/projects/systemd-for-admins-4.html.
Дата: 19.11.2010.

Убиваем службы


Убить системный демон просто, так ведь? Или все же нет?

Конечно, пока демон ограничивается только одним процессом это отчасти верно. Вы выполняете что-то вроде "killall rsyslogd" и syslog'а больше нет. Однако, это не очень хороший способ, т.к. при этом будут убиты все процессы с таким именем, включая те, которые незадачливый пользователь так назвал случайно. Чуть более правильный вариант будет читать .pid файл, т.е. "kill `cat /var/run/syslogd.pid`". Это уже конечно гораздо лучше, но все-таки действительно ли это то, чего мы хотим?

Чаще всего это не так. Рассмотрим службы такие, как Apache, crond или atd, которые порождают дочерние процессы во время своей работы. Такими процессами могут быть настраиваемые пользователем задания для cron, CGI скрипты и даже целые серверные приложения. Если вы убьете основной apache/crond/atd процесс, то дочерние могут продолжить работу. Это значит, что прекращение работы Apache вполне может привести к тому, что CGI-скрипты продолжат выполняться. Причем их "родителем" станет init, что усложнит их опознавание.

Тут нам поможет systemd. Командой "systemctl kill" вы можете легко послать сигнал всем процессам службы. Пример:

# systemctl kill crond.service

При использовании этой команды сигнал SIGTERM гарантированно получат все процессы, относящиеся к службе crond. Конечно, вы также можете посылать и другие сигналы. Например, если вы засранец, вы можете отправить сигнал SIGKILL:

# systemctl kill -s SIGKILL crond.service

Это приведет к тому, что служба будет жестко убита, в полном объеме, независимо от того, как много раз она форкалась, пытаясь сбежать из под надзора.

Иногда все, что вам нужно, это отправить специальный сигнал главному процессу службы. Возможно вы хотите вызвать перезагрузку через SIGHUP. Вместо того, чтобы использовать PID-файл, можно выполнить:

# systemctl kill -s HUP --kill-who=main crond.service

Итак, еще раз о том, что нового для убийства служб есть в systemd? Ну, впервые на Linux мы можем это делать на самом деле правильно. Предыдущие решения всегда зависели от демонов, т.к. завершение порожденных процессов было на их совести. Если же вы хотите использовать SIGTERM и SIGKILL, то это значит, что демоны этого не делают должным образом.

В чем же отличие от systemctl stop? Команда "kill" напрямую посылает сигнал каждому процессу в группу, а "stop" использует заранее сконфигрурированный путь для остановки службы (т.е. вызывает команду, установленную в файле службы параметром ExecStop=).
Как правило, команды "stop" должно быть достаточно. "kill" является более жесткой версией для случаев, когда вы не хотите вызова стандартной команды для остановки, или же служба не завершается другим путем.

(Кстати, при использовании ключа "-s", можно как указывать, так и не указывать префикс "SIG" для названий сигналов. Оба варианта работают.)

Это немного удивительно, что мы так долго на Linux не было способа правильно убить службу. systemd впервые исправляет эту ситуацию.

Полезные ссылки

  1. Леннарт Поттеринг в Google+.
  2. Оригинал статьи.
  3. Перевод на OpenNET.ru.