Строительный портал - Дом. Водонагреватели. Дымоходы. Монтаж отопления. Обогреватели. Оборудование

Создать сервис systemd. Сравнение Systemd или SysVinit или Upstart

Как и ранее, чтобы запустить какой-то скрипт при загрузке системы, вы можете поместить его в файл /etc/rc.d/rc.local . Однако стоит учесть специфику запуска этого скрипта в systemd.

service-файл отвечающего за него юнита выглядит следующим образом:

$ cat /lib/systemd/system/rc-local.service Description=/etc/rc.d/rc.local Compatibility After=network.target Type=forking ExecStart=/etc/rc.d/rc.local start TimeoutSec=0 RemainAfterExit=yes SysVStartPriority=99

Отсюда видно, во-первых, что файл /etc/rc.d/rc.local обязан быть исполняемым.

А во-вторых, видно, что сервис rc-local имеет зависимость только от цели network.target . Параметр SysVStartPriority=99 отвечает только за приоритет по сравнению с другими sysVinit-скриптами, которых в Fedora становится все меньше. С учетом параллельной загрузки это означает, что скрипт, который вы разместите в файле rc.local может быть запущен слишком рано , например, до старта нужных сервисов. Поэтому, если вы разместите в этом файле скрипты перезапуска апача, то, с большой вероятностью, они не сработают.

В версиях до Fedora 17, не было зависимости от network.target , так что, там этот скрипт запускался практически в самом начале.

С помощью systemd-юнита

Более естественный для systemd способ запускать скрипты - это создание своего собственного юнита.

Просто создайте файл /etc/systemd/system/my_stuff.service со следующим текстом:

Description=Run my stuff Requires=network.target After=network.target Type=oneshot RemainAfterExit=True ExecStart=/some/script --with-some-parameters ExecStart=/some/other/script WantedBy=multi-user.target

Здесь Requires - указывает цель, после которой необходимо запустить сервис, After означает, что сеть должна быть полностью запущена к моменту старта, WantedBy - цель, для которой запускается сервис. В ExecStart должен быть указан полный путь к скрипту или исполняемому файлу, поскольку переменная PATH не используется.

multi-user.target - это аналог init 3 в sysVinit. Подробнее о реализации runlevel-ов в systemd, можно прочесть по ссылке .

В такой конфигурации скрипты будут запускаться сразу после запуска сети и старта всех интерфейсов. Однако systemd позволяет гораздо более гибкую настройку. Например, для выполнения скриптов после запуска графического DM можно использовать After: systemd-user-sessions.service

Небольшой пример: После появления облачного хранилища Яндекс.Диск, захотелось автоматически монтировать его в файловую систему через davfs2 (с заранее положенными логином и паролем в /etc/davfs2/secrets). Прописывание в fstab не дало результатов, как и прописывание в rc.local, поскольку в Fedora 16 оба они обрабатывались ещё до поднятия сети. А вот создание модуля по вышеприведённому образцу решило проблему.

Дополнительно

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

Systemctl status rc-local.service

или загляните в файл /var/log/boot.log (он появится если в параметрах загрузки убрать quiet , см.

Здесь покажу как писать инитники для автозапуска какого-либо демона в системе с systemd.

Systemd оперирует unit-файлами в качестве конфигурационных файлов. Это как.conf-файл для upstart или init-скрипты для initd. Unit-файлы также могут описывать и другие системные сущности, но в данном случае они нас интересуют как конфиг для автостарта сервиса. В Ubuntu 16.04 они лежат в /etc/systemd/ . Напишем свой unit-файл.

Допустим у нас есть программа, которую мы хотим запускать как демон. Вот я писал как создать telegram-бота. У меня получился исполняемый файл, который запускается и висит ждет сообщений. Теперь хочу чтобы он как демон стартовал при загрузке системы.

Создаем такой файл:

Description = TelegramBotMonitoring After = network.target Type = simple ExecStart = /usr/local/bin/telegram-site-monitoring -telegrambottoken 397______:___________WRDsIU -chatid -14____640 Restart = always WantedBy = multi-user.target

и кладем его в /etc/systemd/system/telegram-bot.service

Конфиг похож на обычный ini-файл:

    After - запускать этот юнит после определенных демонов или целей (цель - это набор юнитов). Здесь указан network.target , это значит, что демон запустится после того как поднимутся сетевые интерфейсы.

    Type - тип того, как запускается демон. Чаще всего используется simple , forking или one-shot . simple - демон запускается и начинает ожидать на консоле и не отфоркивается. forking - демон запускается, потом форкается и завершает родительский процесс. Многие программы именно так и запускаются, чтобы перейти в background режим. Например, nginx запускается по такой схеме. one-shot - используется для запуска скриптов которые запускаются, отрабатывают и завершаются. В моем случае это не скрипт и программа не форкается, поэтому тип - simple

    ExecStart - команда для запуска демона.

    Restart - рестартовать демон, если он завершится/упадет. При always systemd будет перезапускать демон независимо от того почему он завершился. Можно указать on-failure , тогда будет перезапускаться если демон вышел с ненулевым кодом возврата или был завершен по сигналу (kill DAEMONPID)

    WantedBy - говорим, что запускать этот демон когда система грузится в multi-user режиме

# systemctl daemon-reload

И добавляем созданный юнит в автозагрузку:

# systemctl enable telegram-bot.service Created symlink from /etc/systemd/system/multi-user.target.wants/telegram-bot.service to /etc/systemd/system/telegram-bot.service.```

Все. Сервис добавлен в автозагрузку, но еще не запущен. Запустим:

# systemctl start telegram-bot

Запустился:

# systemctl status telegram-bot ● telegram.service - TelegramBotMonitoring Loaded: loaded (/etc/systemd/system/telegram-bot.service; enabled; vendor preset: enabled) Active: active (running) since Thu 2017-07-13 17:10:19 MSK; 5s ago Main PID: 1825 (telegram-site-m) Tasks: 4 Memory: 4.4M CPU: 39ms CGroup: /system.slice/telegram-bot.service └─1825 /usr/local/bin/telegram-site-monitoring -telegrambottoken 3972____:__________Gi03WRDsIU -chatid -14____40 Jul 13 17:10:19 ubuntu systemd: Started TelegramBotMonitoring. Jul 13 17:10:19 ubuntu telegram-site-monitoring: 2017/07/13 17:10:19 {} Jul 13 17:10:19 ubuntu telegram-site-monitoring: 2017/07/13 17:10:19 Authorized on account Jul 13 17:10:19 ubuntu telegram-site-monitoring: 2017/07/13 17:10:19 Config file: config.json Jul 13 17:10:19 ubuntu telegram-site-monitoring: 2017/07/13 17:10:19 ChatID: Jul 13 17:10:19 ubuntu telegram-site-monitoring: 2017/07/13 17:10:19 Starting monitoring thread

Шпаргалка с коммандами для управления демонами systemd -

Вокруг systemd уже несколько лет ходят «холивары». Systemd пришел к нам на замену System V Init в Linux. Есть как сторонники systemd, так и его противники. Давайте рассмотрим, чем же так плох systemd:

1. Systemd нарушает философию Unix «Делать одну вещь и при этом хорошо», представляя просто сложный набор малосвязных бинарников. Его зона ответственности давно уже выросла за рамки системы инициализации и начинает распространяться на управление питанием, устройствами, точками монтирования, cron-ом, шифровнием диска, API сокетов, журналами (syslog), конфигурацией сети, управлением сессиям, предчтение(readahead), определение разделов, регистрация контейнеров [виртуализация], управление именем хоста-временем-локалью, mDNS/DNS-SD, консоли Linux и прочие штуки - все в одном. На повестке дня - дальнейшее расширение systemd и его внедрение в среду GNU/Linux было выяснено во время «2014 GNOME Asia talk». Дайте нам KISS.

2. Журналы systemd (для journald) сохраняются в очень сложном бинарном формате и могут быть запрошены только journalctl. Это делает журналы потенциально повреждаемыми и они не имеют ACID-совместимых транзакций. Вы бы не хотели, чтобы с системными журналами что-то произошло. Совет от systemd разрабов? Забейте. Единственный путь создать традиционные логи - это запустить syslogd как rsyslog вместе с journald. Так же там есть встроенный HTTP сервер. QR коды тоже можно отдавать через него, с помощью libqrencode.

3. Так как systemd очень завязан на API ядра Linux, разные версии systemd несовместимы с разными ядрами и портируемость бессмысленно снижена в разных компонентах. Это политика изолирования , которая, конечно же, вгоняет экосистему Linux в свою собственную клетку, работая как препятствие в разработке портируемого ПО как с Linux, так и Unix-деривативами. Так же это пораждает трудности с бекпортированием изменений в системой длительной поддержки.

4. udev и dbus становятся обязательными зависимостями. По факту, udev был влит в ветку systemd очень давно. Интеграция менеджера «device node»(который был частью Linux ядра) - это нелегкое решение. Здесь высокая политическая подоплека (имеется в виду политика разработчиков) и много пакетов, зависящих от udev, стали зависимы от systemd, несмотря на форки вроде eudev. Начиная с systemd-209 разработчики ввели собственный нестандартный и малодокументированный sd-bus API, который замещает некоторые задачи libdbus. Далее они решили перенести udev на этот новый транспорт, заменили Netlink и сделали udev наглухо привязанным к systemd демоном. Эффект, конечно, значителен.

5. systemd представляет хелпер который снимает coredump-ы (дампы ядра) и перенаправляет их либо в /var/lib/systemd/coredump либо в journal, где они должны быть запрошены через coredumpctl. Последнее, причем - было поведением по умолчанию и его похоже вернут. Это означает, что пользователей и админов держат за идиотов, но более важно, в основе своей склонная к повреждениям природа логов journald превращает это в серьезную помеху и безответственный выбор при дизайне системы. Также это может создать усложнения в многопользовательских средах в плане привелегий.

6. Размер systemd (видимо, в файлах и мегабайтах - прим.пер.) превращает его в большую «единственную точку отказа». На момент написания systemd имел 9 отчетов CVE (уязвимости) с начала внедрения в марте 2010. Вроде и не много, но его всепроникающая (в плане ответственности за компоненты) и важная суть может стать лакомым кусочком для взломщиков, так как его широта поменьше чем ядро, но настолько же критично по последствиям (прим. пер. - по мне так это уже лицемерие и лукавство.)

7. systemd имеет вирусный характер, его расширения добавляют новые API, но продолжая зависеть именно от его инициализации. Его охват функциональности и расползание как зависимость по куче пакетов означает, что мейнтейнеры дистрибутивов будут обязаны вынуждать переход или сносить напрочь (старое). Например, GNOME обычно использует компоненты systemd вроде logind и поддержка не-systemd систем становится сложной. Под Wayland GNOME использует logind который снова заставляет использовать systemd. Все больше мейнтейнеров прописывают в зависимости systemd по этой причине. Быстрый рост в принятии в такие дистрибутивы, как Debian, Arch Linux, Ubuntu, Fedora, openSUSE показывает, что многие пытаются запрыгнуть в уходящий поезд, иногда бездумно (может тут не точно перевел). Например, странно, что от него зависят Weston compositor, Polkit, upower, udisks2, PackageKit, и тп. Так же ничего особо не дает то, что systemd не хочет запускаться под пользователем.

8. systemd запускает (clusters - теснится, толпится - прим. пер.) себя под PID 1, вместо того чтоб работать как отдельный гипервизор процессов. Так как он контролирует кучу компонентов, существует тьма вариантов, в которых он может помереть (закрашиться) и отправить в небытие всю систему (см. выше про точку отказа). Мы так же отмечаем, что чтобы снизить надобности перезагрузки, systemd предоставляет механизм для перезапуска systemctl в реальном времени. Но если с ним чего не так, то система опять идет крахом. Так же есть разные пути, как это может произойти, включая невозможность прочитать предыдущее несовместимое состояние. Это, похоже, другой пример SPOF (одна точка отказа) и ненужном бремени в и так уже критичном комноненте (init).

9. systemd разработан с glibc-в-уме и не особо поддерживает другие libc-ы. В общем, идея разрабов systemd в стандартной libc библиотеке - та, что баг-в-баг повторит glibc.

10. Сложная «душевная» организация systemd (метафора пер.) делает очень сложной расширение за пределами его собственных рамок (среды) разработки. В то время, как запустить шел скрипт из файлов модулей как-то можно, весьма сложно написать реализацию поведения, которая идет из коробки, с учетом всех этих крутых фич. Много пользователей чаще хотят написать сложные программы, которые прямо взаимодействуют с API systemd, или даже модифицировать (его исходники). Кто-то может побеспокоиться о большом количестве путей в коде в критичной для системы программе, включая возможность того что systemd не синхронизируется с шиной сообщений при загрузке и зависнет. Это противоположно традиционному иниту, который определяем и предсказуем по архитектуре.

11. В конечном счете, распространение systemd символично чуть больше чем просто systemd. Оно показывает радикальный сдвиг в мышлении сообщества Linux. И не обязательно позитивном. Это сдвиг по большей части оринтирован на десктоп, ограничивает выбор, изоляционистский, велосипедостройный и просто огромно-антипаттерный. Если ваша задача потворствовать наименьшему делителю, делайте это. Но мы посмотрим в какую-то другую сторону.

12. systemd вообще похоже не знает что за хренью он хочет быть. Он иногда описан как «system daemon» или как «базовый блок в пространстве пользователя чтобы сделать ОС», оба термина слишком неоднозначны. Он поглощает функциональность которая пренадлежала util-linux, беспроводным инструментам (wireless tools), syslog и прочим проектам. У него нет четкого направления, кроме как причуды самих же разработчиков. Что забавно, несмотря на цели по стандартизации дистрибутивов Linux, у него нет четкого стандарта и он по сути просто катится, как перекати-поле.

systemd - это новый демон инициализации Linux-систем, который в последующем должен прийти на смену классическому демону SysV initd. Основные задачи, которые он призван решить - это, во-первых, ускорение загрузки системы за счёт максимального увеличения количества параллельно запускающихся сервисов, во-вторых, улучшение управляемости системы за счёт использования специфических возможностей, предоставляемых ядром Linux, в-третьих, унификация общесистемных настроек и максимальное обобщение кода запуска различных сервисов. По крайней мере, такие ощущения у меня сложились после ознакомления с документацией.

Хочу поблагодарить Сергея Пташника за отличный перевод документации на systemd: systemd для администратора от автора самой системы, Леннарта Потеринга. Также хочется сказать спасибо за многочисленные примечания к документации, которые всегда оказываются к месту. Эта и последующие мои заметки существенным образом основываются именно на этой документации, а точнее, на её PDF-версии .

1. Установка systemd

Установить systemd довольно просто. Сначала поставим пакет:
# apt-get install systemd И пропишем использование systemd в настройках ядра Linux. Для этого откроем файл с настройками загрузчика GRUB 2:
# vi /etc/default/grub И добавим в настройку GRUB_CMDLINE_LINUX_DEFAULT дополнительную опцию init=/lib/systemd/systemd. После редактирования у меня эта опция стала выглядеть следующим образом:
GRUB_CMDLINE_LINUX="video=VGA-1:640x480 video=TV-1:640x480 rootfstype=ext4 init=/lib/systemd/systemd" Теперь применим изменения, сгенерировав новый файл конфигурации загрузчика:
# update-grub Теперь можно перезагрузить систему, чтобы начать использовать systemd:
# shutdown -r now 2. Решение проблем

2.1. Локализация текстовой консоли

Первая проблема, с которой я столкнулся - это ошибка запуска скрипта console-cyrillic. Этот скрипт должен запускаться при активной текстовой консоли, а systemd запускает все скрипты инициализации асинхронно, в результате чего этот скрипт отрабатывает к моменту, когда уже запущен X-сервер. Как следствие - в консоли вместо русских букв отображаются квадраты, нельзя переключить раскладку и переключиться обратно в графический сеанс.

Console-cyrillic - это устаревший пакет, который остался в моей системе с тех времён, когда я её устанавливал (а было это во времена Etch). Этот пакет имеется в новых версиях Debian и до сих пор поддерживается, однако более универсальной альтернативой для него являются пакеты console-setup и keyboard-configuration. В статье Отображение русского в консоли Ubuntu 11.04 Natty описаны необходимые действия по их настройке.

Установим необходимые пакеты:
# apt-get install console-setup keyboard-configuration Если по каким-то причинам конфигуратор пакетов не был запущен при установке пакетов, можно запустить конфигурирование пакетов принудительно:
# dpkg-reconfigure console-setup # dpkg-reconfigure keyboard-configuration Вообще, в systemd предусмотрены новые файлы конфигурации для настройки текстовой консоли, но в моей системе эти настройки не сработали.

2.2. Сохранение системного времени в аппаратные часы BIOS

При смене настроек времени, по каким-то причинам, не происходит сохранение времени в часах BIOS. Сохранить текущее системное время в аппаратные часы можно с помощью команды:
# hwclock -w Реальное время, которое будет сохранено в часы BIOS, зависит от третьей строчки файла /etc/adjtime. В случае строки UTC будет сохраняться время по Гринвичу, в случае строки LOCAL - будет сохранено время текущего часового пояса.

Нужно отметить, что начиная с Wheezy, настройка UTC удалена из файла /etc/default/rcS и вместо неё теперь используется настройка из файла /etc/adjtime: release-notes: utc/local timezone no longer in /etc/default/rcS .

Корень же проблемы кроется в том, что я использую openntpd, а не ntpd. В случае работающего ntpd в ядре системы включается сохранение текущего системного времени в аппаратный таймер каждые 11 минут. Разработчики systemd посчитали, что этого достаточно. Если же ntpd не используется, то нельзя определить, какие из часов точнее - аппаратные или системные, поэтому и нет смысла предпочитать одни часы другим. В случае необходимости, пользователь должен сам настроить часы вручную необходимым образом.

Для решения этой проблемы я решил написать свой service-файл для демона openntpd. Содержимое service-файла /etc/systemd/system/openntpd.service:
Description=openntpd After=network.target Type=simple ExecStart=/usr/sbin/ntpd -dsf /etc/openntpd/ntpd.conf ExecStartPost=/bin/chown ntpd /var/lib/openntpd/ntpd.drift ExecStop=/sbin/hwclock -w WantedBy=multi-user.target Теперь нужно остановить уже запущенный экземпляр openntpd, сообщить systemd о том, что его конфигурация изменилась:
# systemctl stop openntpd.service # systemctl daemon-reload Включить только что созданный файл сервиса в автозагрузку и запустить openntpd:
# systemctl enable openntpd.service # systemctl start openntpd.service 3. Управление сервисами

Systemd, в отличие от inetd, умеет самостоятельно отслеживать все процессы, порождённые сервисом. Для этого используются так называемые контрольные группы процессов - cgroups. Каждый сервис запускается с собственным идентификатором группы. Все дополнительные процессы, порождаемые в рамках сервиса, так же получают этот идентификатор. Благодаря этому отпадает необходимость в использовании PID-файлов для управления сервисом. Также, благодаря контрольным группам, процессы, порождённые сервисом, никогда не теряются. Например, CGI-процесс будет остановлен вместе с веб-сервером, даже если веб-сервер не позаботится о его остановке и не поместит идентификатор процесса в PID-файл. Процессы пользователей тоже помещаются в отдельную контрольную группу, и отслеживаются подсистемой logind, пришедшей на смену ConsoleKit.

Вторая важная особенность systemd заключается в том, что он обладает собственной системой журналирования, которая называется journald. Эта система агрегирует информацию из разных источников и привязывает её к сервисам. В одном месте с привязкой к сервису собираются сообщения ядра, сообщения процессов, отправленные через syslog, сообщения, отправленные с помощью собственного API journald и сообщения, отправленные процессом на стандартный вывод - STDOUT и на стандартный поток для диагностических сообщений - STDERR. Также systemd отслеживает коды завершения процессов. Благодаря этому, всю диагностическую информацию сервиса можно просматривать в одном месте и удобно диагностировать неисправности.

systemctl - просмотр статусов сервисов. Если вывод команды не перенаправляется куда-либо, а попадает на консоль, то для просмотра статусов сервисов автоматически запускается программа-пейджер, обычно это less,
systemctl status openntpd.service - подробный просмотр статуса указанного сервиса (openntpd),
systemctl status --follow openntpd.service - просмотр статуса указанного сервиса (openntpd) с выводом сообщений от сервиса в процессе их поступления. У этой опции есть более короткий аналог - -f, который в моей системе по каким-то причинам не заработал. Возможно дело в том, что опция -f имеет ещё второе значение - --force и systemctl не умеет определять, какая именно из опций имеется в виду,
systemctl status -n10 openntpd.service - просмотр статуса указанного сервиса (openntpd) с выводом 10 последних сообщений сервиса,
systemctl reset-failed - сброс всех статусов завершения, отображаемых по команде просмотра статуса сервиса,
systemd-cgls - просмотр иерархии контрольных групп процессов (нечто подобное можно получить при помощи команды ps xawf -eo pid,user,cgroups,args),
systemctl daemon-reload - перезагрузка конфигурации systemd,
systemctl start openntpd.service - запуск указанного сервиса (openntpd), аналогично update-rc.d openntpd start для SysV initd,
systemctl stop openntpd.service - остановка указанного сервиса (openntpd), аналогично update-rc.d openntpd stop для SysV initd,
systemctl restart openntpd.service - перезапуск указанного сервиса (openntpd),
systemctl enable openntpd.service - включение запуска указанного сервиса (openntpd) при загрузке системы, аналогично update-rc.d openntpd enable для SysV initd,
systemctl disable openntpd.service - отключение запуска указанного сервиса (openntpd) при загрузке системы, аналогично update-rc.d openntpd disable для SysV initd,
systemctl mask openntpd.service - запрет запуска указанного сервиса (openntpd), его даже будет нельзя запустить вручную,
systemctl unmask openntpd.service - разрешение запуска указанного сервиса (openntpd), его можно будет запустить вручную, также будет разрешён запуск при загрузке системы, если он был настроен,
systemctl kill openntpd.service - отправка сигнала (по умолчанию отправляется сигнал SIGTERM) всем процессам в контрольной группе сервиса (openntpd),
systemctl kill -s SIGKILL openntpd.service - отправка сигнала SIGKILL всем процессам в контрольной группе сервиса (openntpd). Можно также использовать сокращённое название сигнала - KILL,
systemctl kill -s HUP --kill-who=main crond.service - отправка сигнала SIGHUP главному процессу контрольной группы сервиса (crond). Этот пример заставит crond перечитать файл конфигурации, при этом задания, запущенные crond этот сигнал не получат и продолжат нормальную работу,
systemctl help openntpd.service - просмотр документации сервиса (не работает в Debian Wheezy),
systemd-analyze blame - вывод списка сервисов, отсортированного по убыванию времени, потраченного на их запуск. Команда может быть полезной для поиска узких мест в процессе инициализации системы,
systemd-analyze plot > plot.svg - вывод временнОй диаграммы в формате SVG, иллюстрирующей последовательность (и параллельность) запуска сервисов.

4. Новые файлы конфигурации системы

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

Кроме того, поскольку теперь все сервисы будут запускаться с помощью service-файлов, отпадает необходимость в использовании файлов, включаемых в shell-скрипты. Это файлы, располагающиеся в каталогах /etc/default (семейство Debian) и /etc/sysconfig (семейство RedHat). Поскольку в service-файлах ориентироваться намного проще, чем в shell-скриптах, нет необходимости выносить настройки сервисов в отдельные файлы - все необходимые настройки можно вписать прямо в service-файл.

Перечислим новые файлы конфигурации, вводимые systemd:

/etc/hostname - сетевое имя системы,
/etc/vconsole.conf - настройки шрифта системной консоли и раскладки клавиатуры,
/etc/locale.conf - языковые настройки системы,
/etc/modules-load.d/*.conf - каталог для перечисления модулей ядра, которые нужно принудительно загрузить при загрузке системы,
/etc/sysctl.d/*.conf - каталог для настроек параметров ядра, дополняет классический файл /etc/sysctl.conf,
/etc/tmpfiles.d/*.conf - каталог для управления настройками временных файлов,
/etc/binfmt.d/*.conf - каталог для регистрации форматов исполняемых файлов, например форматов Java, Mono, WINE,
/etc/os-release - файл с идентификатором дистрибутива и его версии,
/etc/machie-id - файл с постоянным уникальным идентификатором системы,
/etc/machie-info - файл с описательным сетевым именем системы. Здесь же настраивается значок системы, который будет отображаться в графических оболочках. Файл обслуживается демоном systemd-hostnamed.

5. Подсистема журналирования journald

Как уже было сказано, systemd вводит новую систему журналирования, которая собирает информацию из разных источников (сообщения ядра, сообщения, отправленные в syslog, на стандартный вывод STDOUT и на стандартный поток диагностических сообщений STDERR) в одном месте. Эта система не заставляет отказываться от стандартного демона журналирования syslog - можно пользоваться обеими системами журналирования параллельно.

Journald использует для хранения журнальной информации два каталога:
/run/log/journal - каталог с кольцевым буфером последних сообщений,
/var/log/journal - каталог с постоянным хранением всех сообщений.

По умолчанию используется только первый каталог, а для включения постоянного хранения всех сообщений второй каталог нужно создать вручную (в Debian Wheezy этот каталог создаётся автоматически, при установке systemd, а первый каталог не используется):
# mkdir -p /var/log/journald После этого можно, но совершенно не обязательно, удалить стандартный демон журналирования rsyslog или ng-syslog.

Настройки демона journald в Debian Wheezy хранятся в файле /etc/systemd/systemd-journald.conf . В частности, там можно задать настройки сжатия файла журнала, задать лимит размера файлов журнала, настроить дублирование сообщений в системную консоль или в демон syslog.

Пользователь root и пользователи из группы adm имеют доступ ко всем сообщениям в журнале, а обычные пользователи - только к сообщениям, сгенерированным их процессами.

Для просмотра сообщений из журнала в Debian Wheezy можно воспользоваться командой systemd-journalctl (в руководстве указана команда journalctl):
systemd-journalctl - просмотр всех сообщений. Как и в случае systemctl, если вывод команды никуда не перенаправляется, а попадает на консоль, для более удобного просмотра сообщений автоматически запускается программа-пейджер, обычно less,
systemd-journalctl -f - просмотр сообщений в процессе их поступления,
systemd-journalctl -n10 - просмотр 10 последних сообщений,
systemd-journalctl -b - просмотр сообщений, сгенерированных с момента загрузки системы (не работает в Debian Wheezy),
systemd-journalctl -b -p err - просмотр сообщений, сгенерированных с момента загрузки системы и имеющих приоритет error или выше (не работает в Debian Wheezy),
systemd-journalctl --since=yesterday - просмотр всех сообщений, сгенерированных со вчерашнего дня (не работает в Debian Wheezy),
systemd-journalctl --since=2012-10-15 --until="2012-10-16 23:59:59" - просмотр всех сообщений, сгенерированных 15 и 16 октября 2012 года (не работает в Debian Wheezy),
systemd-journalctl -u httpd --since=00:00 --until=09:30 - просмотр всех сообщений, сгенерированных пользователем httpd сегодня с полуночи до полдесятого (не работает в Debian Wheezy),
systemd-journalctl /dev/sdc - просмотр всех сообщений, упоминающих диск sdc (не работает в Debian Wheezy),
systemd-journalctl /usr/sbin/vpnc - просмотр всех сообщений от процессов /usr/sbin/vpnc (не работает в Debian Wheezy),
systemd-journalctl /usr/sbin/vpnc /usr/sbin/dhclient - просмотр всех сообщений от процессов /usr/sbin/vpnc и /usr/sbin/dhclient, объединённый и отсортированный по времени (не работает в Debian Wheezy),

Кроме простого просмотра текстовых сообщений имеется возможность просматривать метаданные, которые journald самостоятельно добавляет к каждой записи в журнале. Чтобы увидеть эти поля, достаточно воспользоваться следующей опцией, переключающей формат вывода данных:
systemd-journalctl -o verbose - выводит вместе с сообщением из журнала все сопутствующие сообщению метаданные в удобном для восприятия человеком виде. Другие доступные форматы: export - тот же самый формат verbose, но без отступов, json - вывод в формате JSON, cat - вывод только текста сообщений без каких-либо дополнительных данных.

Названия полей, начинающиеся со знака подчёркивания, можно использовать для фильтрации сообщений. Журнал индексируется по всем полям, поэтому поиск выполняется быстро. Примеры фильтрации сообщений по метаданным:
systemd-journalctl _UID=70 - вывод всех сообщений от процессов пользователя с идентификатором 70,
systemd-journalctl _UID=70 _UID=71 - вывод всех сообщений от процессов пользователей с идентификаторами 70 и 71. Указание одноимённых полей автоматически подразумевает операцию логического ИЛИ,
systemd-journalctl _HOSTNAME=epsilon _COMM=avahi-daemon - вывод всех сообщений от процессов с именем avahi-daemon, работающих на компьютере с именем epsilon. В данном случае указаны разные поля, поэтому подразумевается операция логического И,
systemd-journalctl _HOSTNAME=theta _UID=70 + _HOSTNAME=epsilon _COMM=avahi-daemon - вывод сообщений, соответствующих любому из двух фильтров, объединённых знаком +. Знак + указывает явную операцию логического ИЛИ, которая имеет более низкий приоритет, чем И,
systemd-journalctl -F _SYSTEMD_UNIT - вывод всех значений поля _SYSTEMD_UNIT, имеющихся в журнале. Полученные значения можно использовать для фильтрации интересующих записей (не работает в Debian Wheezy).

Systemd – это система инициализации и системный менеджер, который становится новым стандартом для Linux-машин. Споры о продуктивности systemd по сравнению с традиционными системами инициализации SysV ведутся до сих пор, тем не менее, эту систему планируют внедрить большинство дистрибутивов, а многие уже сделали это.

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

Данный мануал научит вас работать с командой systemctl, главным инструментом управления системы инициализации systemd. Вы узнаете, как управлять сервисами, проверять состояние и работать с конфигурационными файлами.

Управление сервисами

Основная цель init-системы – инициализировать компоненты, которые должны запускаться после загрузки ядра Linux (традиционно они называются «пользовательскими» компонентами). Система инициализации также используется для управления сервисами и демонами сервера. Имея это в виду, начнем знакомство с systemd с простых операций управления сервисами.

В systemd целью большинства действий являются юниты – ресурсы, которыми systemd может управлять. Юниты делятся на категории по типам ресурсов, которые они представляют. Юниты определяются в так называемых юнит-файлах. Тип каждого юнита можно определить по суффиксу в конце файла.

Для задач управления сервисами предназначены юнит-файлы с суффиксом.service. Однако в большинстве случаев суффикс.service можно опустить, так как система systemd достаточно умна, чтобы без суффикса определить, что нужно делать при использовании команд управления сервисом.

Запуск и остановка сервиса

Чтобы запустить сервис systemd, используйте команду start. Если вы работаете не в сессии пользователя root, вам нужно использовать sudo, поскольку эта команда повлияет на состояние операционной системы:

sudo systemctl start application.service

Как уже говорилось ранее, systemd знает, что для команд управления сервисами нужно искать файлы *.service, поэтому эту команду можно ввести так:

sudo systemctl start application

Вышеуказанный формат можно использовать в повседневной работе, но в мануале для ясности мы будем использовать суффикс.service.

Чтобы остановить сервис, достаточно ввести команду stop:

sudo systemctl stop application.service

Перезапуск и перезагрузка

Чтобы перезапустить сервис, используйте restart:

sudo systemctl restart application.service

Если указанное приложение может перезагрузить свои конфигурационные файлы (без перезапуска), можно использовать reload:

sudo systemctl reload application.service

Если вы не знаете, может ли сервис перезагрузить свои файлы, используйте команду reload-or-restart. Она перезагрузит сервис, а если это невозможно – перезапустит его.

sudo systemctl reload-or-restart application.service

Включение и отключение сервисов

Приведенные выше команды необходимы при работе с сервисом в текущей сессии. Чтобы добавить сервис в автозагрузку systemd, его нужно включить.

Для этого существует команда enable:

sudo systemctl enable application.service

Это создаст символическую ссылку на копию файла сервиса (обычно в /lib/systemd/system или /etc/systemd/system) в точке на диске, где systemd ищет файлы для автозапуска (обычно /etc/systemd/system/some_target.target.want, подробнее об этом — дальше в руководстве).

Чтобы убрать сервис из автозагрузки, нужно ввести:

sudo systemctl disable application.service

Имейте в виду, что включение сервиса не запускает его в текущей сессии. Если вы хотите запустить сервис и включить его в автозагрузку, вам нужно запустить команды start и enable.

Проверка состояния сервиса

Чтобы проверить состояние сервиса, введите:

systemctl status application.service

Эта команда выведет состояниесервиса, иерархию групп и первые несколько строк лога.

Например, при проверке состояния сервера Nginx вы можете увидеть такой вывод:

nginx.service - A high performance web server and a reverse proxy server
Loaded: loaded (/usr/lib/systemd/system/nginx.service; enabled; vendor preset: disabled)
Active: active (running) since Tue 2015-01-27 19:41:23 EST; 22h ago
Main PID: 495 (nginx)
CGroup: /system.slice/nginx.service
├─495 nginx: master process /usr/bin/nginx -g pid /run/nginx.pid; error_log stderr;
└─496 nginx: worker process
Jan 27 19:41:23 desktop systemd: Starting A high performance web server and a reverse proxy server...
Jan 27 19:41:23 desktop systemd: Started A high performance web server and a reverse proxy server.

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

Существуют также методы проверки конкретных состояний. Например, чтобы проверить, активен ли данный юнит (запущен ли он), вы можете использовать команду is-active:

systemctl is-active application.service

Это отобразит текущее состояние юнита, обычно это active или inactive. Код завершения будет «0», если юнит активен, что упрощает процесс анализа.

Чтобы узнать, включен ли юнит, вы можете использовать команду is-enabled:

systemctl is-enabled application.service

Эта команда сообщит, включен ли сервис, и снова определит код завершения как «0» или «1» в зависимости от результата.

Третья команда позволяет определить, находится ли юнит в состоянии сбоя. Это указывает на то, что возникла проблема с запуском рассматриваемого юнита:

systemctl is-failed application.service

Команда вернет active, если юнит работает правильно, и failed, если случилась ошибка. Если юнит был остановлен намеренно, команда может вернуть unknown или inactive. Код завершения «0» означает, что произошел сбой, а «1» указывает на любое другое состояние.

Обзор состояния системы

Ранее мы рассмотрели команды, необходимые для управления отдельными сервисами, но они не очень полезны для изучения текущего состояния системы. Существует несколько команд systemctl, которые предоставляют эту информацию.

Просмотр списка текущих юнитов

Чтобы запросить список текущих юнитов systemd, используйте команду list-units:

systemctl list-units

Эта команда покажет список всех юнитов, которые в настоящее время существуют в системе systemd. Результат будет выглядеть примерно так:

UNIT LOAD ACTIVE SUB DESCRIPTION
atd.service loaded active running ATD daemon
avahi-daemon.service loaded active running Avahi mDNS/DNS-SD Stack
dbus.service loaded active running D-Bus System Message Bus
dcron.service loaded active running Periodic Command Scheduler
dkms.service loaded active exited Dynamic Kernel Modules System
[email protected] loaded active running Getty on tty1
. . .

В выводе есть такие столбцы:

  • UNIT – название юнита systemd.
  • LOAD – сообщает, была ли конфигурация юнита обработана systemd. Конфигурация загруженных юнитов хранится в памяти.
  • ACTIVE – сводное состояние юнита. Обычно это позволяет быстро определить, успешно ли запущен текущий юнит.
  • SUB: состояние более низкого уровня, которое сообщает подробную информацию об устройстве. Это часто зависит от типа юнита, состояния и фактического метода, в котором запущен юнит.
  • DESCRIPTION – краткое описание функций юнита.

Поскольку команда list-units показывает по умолчанию только активные юниты, все вышеперечисленные записи будут показывать loaded в столбце LOAD и active в столбце ACTIVE. Такой формат является поведением systemctl по умолчанию при вызове без дополнительных команд, поэтому вы увидите то же самое, если вы вызываете systemctl без аргументов:

С помощью systemctl можно запрашивать различную информацию путем добавления флагов. Например, чтобы увидеть все юниты, которые загрузила (или попыталась загрузить) система systemd, независимо от того, активны ли они в данный момент, вы можете использовать флаг -all:

systemctl list-units --all

Эта команда сообщит о юнитах, которые загрузила или попыталась загрузить система systemd, независимо от их текущего состояния. После запуска некоторые юниты становятся неактивными, а юниты, которые пыталась загрузить systemd, не были найдены на диске.

Вы можете использовать другие флаги для фильтрации результатов. Например, флаг —state= можно использовать для определения состояний LOAD, ACTIVE или SUB. Флаг —all нужно оставить, чтобы система отображала неактивные юниты:

systemctl list-units --all --state=inactive

Еще один популярный фильтр – это —type=. Он позволяет отфильтровать юниты по типу. К примеру, чтобы запросить только активные юниты, можно ввести:

systemctl list-units --type=service

Список юнит-файлов

Команда list-units отображает только юниты, которые система systemd попыталась обработать и загрузить в память. Поскольку systemd избирательно читает только те юнит-файлы, которые кажутся ей необходимыми, список не будет включать все доступные юнит-файлы. Чтобы просмотреть список всех доступных юнит-файлов (включая те, что systemd не пыталась загрузить), используйте команду list-unit-files.

systemctl list-unit-files

Юниты являются представлениями ресурсов, о которых знает systemd. Поскольку systemd не обязательно читает все определения юнитов, она представляет только информацию о самих файлах. Вывод состоит из двух столбцов: UNIT FILE и STATE.

UNIT FILE STATE
proc-sys-fs-binfmt_misc.automount static
dev-hugepages.mount static
dev-mqueue.mount static
proc-fs-nfsd.mount static
proc-sys-fs-binfmt_misc.mount static
sys-fs-fuse-connections.mount static
sys-kernel-config.mount static
sys-kernel-debug.mount static
tmp.mount static
var-lib-nfs-rpc_pipefs.mount static
org.cups.cupsd.path enabled
. . .

Обычно столбец STATE содержит значения enabled, disabled, static или masked. В этом контексте static означает, что в юнит-файле нет раздела install, который используется для включения юнита. Таким образом, эти юниты невозможно включить. Обычно это означает, что юнит выполняет одноразовое действие или используется только как зависимость другого юнита и не должен запускаться сам по себе.

Управление юнитами

Теперь вы знаете, как работать с сервисами и отображать информацию о юнитах и юнит-файлах, о которых знает systemd. Получить более конкретную информацию о юнитах можно с помощью некоторых дополнительных команд.

Отображение юнит-файла

Чтобы отобразить юнит-файл, который загрузила systemd, вы можете использовать команду cat (была добавлена в версии systemd 209). Например, чтобы увидеть юнит-файл демона планирования atd, можно ввести:

systemctl cat atd.service
Description=ATD daemon
Type=forking
ExecStart=/usr/bin/atd
WantedBy=multi-user.target

На экране вы увидите юнит-файл, который известен текущему запущенному процессу systemd. Это может быть важно, если вы недавно изменяли файлы модулей или если вы переопределяете некоторые параметры в фрагменте юнит-файла (об этом поговорим позже).

Отображение зависимостей

Чтобы просмотреть дерево зависимостей юнита, используйте команду:

systemctl list-dependencies sshd.service

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

sshd.service
├─system.slice
└─basic.target
├─microcode.service
├─rhel-autorelabel-mark.service
├─rhel-autorelabel.service
├─rhel-configure.service
├─rhel-dmesg.service
├─rhel-loadmodules.service
├─paths.target
├─slices.target
. . .

Рекурсивные зависимости отображаются только для юнитов.target, которые указывают состояния системы. Чтобы рекурсивно перечислить все зависимости, добавьте флаг —all.

Чтобы показать обратные зависимости (юниты, зависящие от указанного элемента), вы можете добавить в команду флаг —reverse. Также полезными являются флаги —before и —after, они отображают юниты, которые зависят от указанного юнита и запускаются до или после него.

Проверка свойств юнита

Чтобы увидеть низкоуровневые свойства юнита, вы можете использовать команду show. Это отобразит список свойств указанного юнита в формате ключ=значение.

systemctl show sshd.service
Id=sshd.service
Names=sshd.service
Requires=basic.target
Wants=system.slice
WantedBy=multi-user.target
Conflicts=shutdown.target
Before=shutdown.target multi-user.target
After=syslog.target network.target auditd.service systemd-journald.socket basic.target system.slice
Description=OpenSSH server daemon
. . .

Чтобы отобразить одно из свойтсв, передайте флаг –р и укажите имя свойства. К примеру, чтобы увидеть конфликты юнита sshd.service, нужно ввести:

systemctl show sshd.service -p Conflicts
Conflicts=shutdown.target

Маскировка юнитов

Systemd может блокировать юнит (автоматически или вручную), создавая симлинк на /dev/null. Это называется маскировкой юнитов и выполняется командой mask:

sudo systemctl mask nginx.service

Теперь сервис Nginx не будет запускаться автоматически или вручную до тех пор, пока включена маскировка.

Если вы проверите list-unit-files, вы увидите, что сервис отмечен как masked:

systemctl list-unit-files
. . .
kmod-static-nodes.service static
ldconfig.service static
mandb.service static
messagebus.service static
nginx.service masked
quotaon.service static
rc-local.service static
rdisc.service disabled
rescue.service static
. . .

Если вы попробуете запустить сервис, вы получите такое сообщение:

sudo systemctl start nginx.service
Failed to start nginx.service: Unit nginx.service is masked.

Чтобы раскрыть (разблокировать) юнит и сделать его доступным, используйте unmask:

sudo systemctl unmask nginx.service

Это вернет сервис в его прежнее состояние.

Редактирование юнит-файлов

Хотя конкретный формат юнит-файлов не рассматривается в данном руководстве, systemctl предоставляет встроенные механизмы для редактирования и изменения юнит-файлов. Эта функциональность была добавлена в systemd версии 218.

Команда edit по умолчанию открывает сниппет юнит-файла:

sudo systemctl edit nginx.service

Это будет пустой файл, который можно использовать для переопределения или добавления директив в определение юнита. В каталоге /etc/systemd/system будет создан каталог, который содержит имя устройства с суффиксом.d. Например, для nginx.service будет создан каталог nginx.service.d.

Внутри этого каталога будет создан сниппет с именем override.conf. Когда юнит загружается, systemd объединит в памяти сниппет для переопределения с остальным юнит-файлом. Директивы сниппета будут иметь приоритет над теми, что указаны в исходном юнит-файле.

Если вы хотите отредактировать весь юнит-файл вместо создания сниппета, вы можете передать флаг —full:

sudo systemctl edit --full nginx.service

Это загрузит текущий юнит-файл в редактор, где его можно будет изменить. Когда редактор закроется, измененный файл будет записан в /etc/systemd/system и будет иметь приоритет над определением юнита системы (обычно он находится где-то в /lib/systemd/system).

Чтобы удалить все сделанные вами дополнения, удалите каталог конфигурации.d или измененный файл сервиса из /etc/systemd/system. Например, чтобы удалить сниппет, можно ввести:

sudo rm -r /etc/systemd/system/nginx.service.d

Чтобы удалить полный отредактированный файл, введите:

sudo rm /etc/systemd/system/nginx.service

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

sudo systemctl daemon-reload

Изменение уровней запуска

Цели – это специальные юнит-файлы, которые описывают уровни системы или точки синхронизации. Как и другие юниты, файлы целей можно определить по суффиксу. В данном случае используется суффикс.target. Сами по себе цели ничего не делают, вместо этого они используются для группировки других юнитов.

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

Например, есть цель swap.target, которая используется для того, что чтобы сообщить, что swap готов к использованию. Юниты, которые являются частью этого процесса, могут синхронизироваться с этой целью при помощи директив WantedBy= или RequiredBy=. Юниты, которым нужен своп, могут указывать это условие через спецификации Wants=, Requires= или After=.

Проверка и настройка целей по умолчанию

Процесс systemd имеет цель по умолчанию, которую он использует при загрузке системы. Обеспечение ряда зависимостей этой единственной цели приводит систему в желаемое состояние. Чтобы найти цель по умолчанию, введите:

systemctl get-default
multi-user.target

Если вы хотите установить другую цель по умолчанию, вы можете использовать set-default. Например, если у вас установлен графический рабочий стол и вы хотите, чтобы система загружала его по умолчанию, вы можете соответствующим образом изменить цель:

sudo systemctl set-default graphical.target

Список доступных целей

Просмотреть список доступных целей можно с помощью команды:

systemctl list-unit-files --type=target

В отличие от уровней запуска, одновременно можно включать несколько целей. Активная цель указывает, что systemd будет пытаться запустить все юниты, привязанные к этой цели, и не попытается их отключить. Чтобы увидеть все активные цели, введите:

systemctl list-units --type=target

Изоляция целей

Можно запустить все юниты, связанные с целью, и остановить все юниты, которые не являются частью дерева зависимостей. Для этого используется команда isolate. Она похожа на изменение уровня запуска в других системах инициализации.

Например, если вы работаете в графической среде, где активна цель graphical.target, вы можете отключить графическую систему и перевести систему в состояние многопользовательской командной строки, изолировав multi-user.target. Поскольку graphical.target зависит от multi-user.target, но не наоборот, все графические юниты будут остановлены.

Вы можете взглянуть на зависимости изолируемой цели, прежде чем выполнять эту процедуру, чтобы убедиться, что вы не останавливаете жизненно важные сервисы:

systemctl list-dependencies multi-user.target

Если вас все устраивает, можете изолировать цель:

sudo systemctl isolate multi-user.target

Сокращения

Существуют цели, определенные для важных событий, таких как выключение или перезагрузка. systemctl также предлагает несколько сокращений для быстрого вызова.

К примеру, чтобы перевести систему в режим отладки, можно ввести просто rescue вместо isolate rescue.target:

sudo systemctl rescue

Это обеспечит дополнительную функциональность – оповестит всех пользователей системы о событии.

Чтобы остановить систему, вы можете использовать команду halt:

sudo systemctl halt

Чтобы начать полное завершение работы, вы можете использовать команду poweroff:

sudo systemctl poweroff

Перезапуск можно начать с помощью команды reboot:

sudo systemctl reboot

Эти команды сообщат пользователям системы о событиях, чего не сделает стандартная команда. Обратите внимание, большинство машин используют более короткие команды для этих операций, чтобы они работали правильно с systemd.

Например, чтобы перезагрузить систему, вы можете ввести просто:

Заключение

Теперь вы знакомы с основными механизмами systemctl и знаете, как управлять системой инициализации с помощью этого инструмента.

Хотя systemctl работает в основном с процессом systemd, в системе systemd есть другие компоненты, которые контролируются другими утилитами. К примеру, для управления логированием и пользовательскими сеансами используются отдельные демоны и утилиты (journald/journalctl и logind/loginctl соответственно).

Похожие публикации