Systemctl удалить сервис. Запуск собственных скриптов systemd. Проверка состояния служб

Systemd Unit — это скрипт, который выполняет различные действия (все то, что пропишешь в него). Я обычно пишу такие скрипты для запуска различных служб которые компилирую руками или когда использую готовое ПО.

Что дадут вам Systemd юниты?

Units — это объекты, которыми может управлять система (В основном — стандартизированное представление системных ресурсов, которыми может управлять набор демонов).

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

Некоторые функции, которые легко реализовать:

  • Активация на основе сокетов : Сокеты, связанные с сервисом, лучше всего вырываются из самого демона, чтобы обрабатываться отдельно. Это дает ряд преимуществ,- например, задержка запуска службы до тех пор, пока соответствующий сокет не будет доступен. Это также позволяет системе создавать все сокеты до начала запуска процесса, что позволяет параллельно загружать связанные службы.
  • Активация на основе шины : Unit-ы также могут быть активированы на интерфейсе шины, предоставляемом D-Bus-ом. Устройство может быть запущено когда соответствующая шина доступна.
  • Активация на основе пути: Unit может быть запущен на основе активности или наличия определенных путей к файловой системе. Это использует inotify.
  • Активация на основе устройства : Unit-ы также могут быть запущены при первой доступности (подключении) связанного оборудования за счет использования событий udev.
  • Неявное сопоставление зависимостей: Большая часть структуры зависимостей для юнитов может быть построена самой системой. Вы все равно можете добавить информацию о зависимостях, но большая часть тяжелой работы будет решена за вас.
  • Экземпляры и шаблоны: Файлы блока шаблонов могут использоваться для создания нескольких экземпляров одного и того же общего устройства. Это позволяет создавать небольшие вариации или единичные unit-ы, которые обеспечивают одну и ту же общую функцию.
  • Простое упрощение безопасности: Юниты могут реализовать некоторые довольно хорошие функции безопасности, добавив простые директивы. Например, вы можете указать какой доступ можно использовать (чтение, запись) при работе с файловой системой, ограничить возможности ядра, установить приватный /tmp фолдер и сетевой доступ.
  • Drop-ins и snippets : Units можно легко расширить, предоставив фрагменты, которые будут отменять части файла системы. Это позволяет легко переключаться между vanilla и индивидуальными реализациями.

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

Как я могу найти/ Где находятся Systemd Unit в Unix/Linux?

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

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

Если вы хотите изменить работу некоторого устройства, то для этого нужно перейти в /etc/systemd/system директорию, потому что — файлы, найденные в этом каталоге, имеют приоритет над любыми другими местами в файловой системы.

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

Правильный способ сделать это — создать каталог с именем после файла с добавлением «.d» в конце. Таким образом, для единицы под названием my_test.service нужно создать подкаталог my_test.service.d. В этом каталоге файл, заканчивающийся на.conf, может использоваться для переопределения или расширения атрибутов unit файла.

Также есть место для определения run-time unit-ов в /run/systemd/system. Файлы, найденные в этом каталоге, имеют приоритет между /etc/systemd/system и/lib/systemd/system.

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

Типы systemd Unit файлов

Самый простой способ определить тип устройства — это посмотреть на его суффикс, который добавляется к концу имени ресурса (юнита). В следующем списке описаны типы unit-ов, доступных для systemd:

  • .service : Данный юнит описывает, как управлять службой или приложением на сервере. Он в себе будет включать запуск или остановку службу, при каких обстоятельствах она должна автоматически запускаться, а также информацию о зависимости для соответствующего программного обеспечения.
  • .socket : Файл сокет-устройства описывает сетевой, IPC-сокет или FIFO буфер, который systemd использует для активации сокета. Они всегда имеют связанный.service файл, который будет запущен при сокет активности, которая определяет этот блок.
  • .device : Юнит, который описывает устройство, которое было указано как необходимое для управления systemd с помощью udev или файловой системы sysfs. Не все устройства имеют файлы.device. Некоторые скрипты, которым может потребоваться устройства.device, предназначены для монтирования и доступа к устройствам.
  • .mount : Этот блок определяет точку монтирования в системе, которой управляет systemd. Они называются по пути монтирования, при этом «/» изменены на тире. Записи внутри /etc/fstab могут иметь блоки, созданные автоматически.
  • .automount : Модуль.automount настраивает точку монтирования, которая будет автоматически установлена и должен быть определен после точки монтирования, на которую они ссылаются, и должны иметь соответствующий модуль.mount для определения особенностей монтирования.
  • .swap : Данный юнит, описывает SWAP (пространство подкачки) в системе. Название этих блоков должно отражать путь к устройству или файлу.
  • .target : Данный юнит используется для обеспечения точек синхронизации для других устройств при загрузке или изменения состояний. Они также могут использоваться для перевода системы в новое состояние.
  • .path : Данный юнит, определяет путь, который может использоваться для активации на основе пути. По умолчанию, юнит будет запущен с тем же базовым именем. Это использует inotify для отслеживания изменения путей.
  • .timer : Этот юнит, определяет таймер, который будет управляться systemd (аналог cron джоб) для задержки или запланированной активации. При достижении таймера будет запускаться соответствующий блок.
  • .snapshot : Это юнит, создается автоматически командой snapshot systemctl. Он позволяет вам восстановить текущее состояние системы после внесения изменений. Снимки не сохраняются во время сеансов и используются для отката временных состояний.
  • .slice : Он связан с узлами группы управления Linux, что позволяет ограничить ресурсы или назначить их для любых процессов, связанных с slice. Имя отражает его иерархическую позицию внутри дерева групп. Юниты размещаются в определенных slice по умолчанию в зависимости от их типа.
  • .scope : Они создаются автоматически systemd из информации которую получили от его интерфейса шины. Они используются для управления наборами системных процессов, созданных извне.

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

Структура systemd Unit файлов

Внутренняя структура файлов организована с помощью разделов. Разделы обозначаются двумя квадратными скобками «[» и «]» с именем раздела, заключенного внутри. Каждый раздел продолжается до начала следующего раздела или до конца файла.

Названия разделов хорошо определены и учитывают регистр. Таким образом, раздел не будет интерпретироваться правильно, если он записан как . Если вам нужно добавить нестандартные разделы для анализа (отличными от systemd), вы можете добавить X-префикс к имени раздела.

В этих разделах поведение устройства и метаданные определяются с помощью простых директив с использованием формата ключа-значения с назначением, обозначенным знаком равенства, например:

Directive1=value Directive2=value .......

В случае переопределения файла (например, содержащегося в каталоге unit.type.d) директивы могут быть сброшены путем назначения пустой строкой. Например, копия единичного файла системы может содержать директиву, заданную таким образом:

Directive1=default_value

Значение default_value можно исключить в файле переопределения, указав Directive1 (без значения), например:

Directive1=

Сейчас рассмотрим каждый из юнитов по отдельности.

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

Хотя порядок разделов не имеет значения для systemd при парсинге файла, этот раздел часто размещается сверху, потому что он предоставляет обзор устройства. Некоторые общие директивы, которые вы найдете в разделе :

  • Description= : Эта директива может использоваться для описания имени и основных функций устройства. Он возвращается различными инструментами systemd, поэтому полезно установить что-то короткое, конкретное и информативное.
  • Documentation= : Эта директива предоставляет местоположения документации. Это могут быть внутренние доступные справочные страницы, либо доступные в интернете (URL-адреса). Команда «status system your_service» выведет эту информацию.
  • Requires= : В этой директиве перечислены все юниты, от которых зависит этот юнит (служба или устройство). Если текущий блок активирован, перечисленные здесь юниты также должны успешно активироваться, иначе он потерпит неудачу. Эти блоки запускаются параллельно с текущим устройством по умолчанию.
  • Wants= : Эта директива похожа на Requires=, но менее строгая. Systemd будет пытаться запустить любые юниты, перечисленные здесь, когда это устройство активировано. Если эти устройства не обнаружены или не запущены, текущий блок будет продолжать функционировать. Это рекомендуемый способ настройки большинства зависимостей. Опять же, это подразумевает параллельную активацию, если не изменено другими директивами.
  • BindsTo= : Эта директива аналогична Requires =, но также приводит к остановке текущего устройства, когда соответствующий узел завершается.
  • Before= : Юниты, перечисленные в этой директиве, не будут запущены до тех пор, пока текущий блок не будет отмечен как запущенный, если они будут активированы одновременно.
  • After= : Юниты, перечисленные в этой директиве, будут запущены до запуска текущего устройства (юнита).
  • Conflicts= : Данный юнит можно использовать для отображения юнитов, которые нельзя запускать одновременно с текущим устройством. Запуск устройства с этой связью приведет к остановке других устройств.
  • Condition…= : Существует ряд директив, начинающихся с условия, которые позволяют администратору протестировать определенные условия до запуска устройства. Это можно использовать для предоставления файла универсального элемента, который будет запускаться только в соответствующих системах. Если условие не выполнено, юнит — пропускается.
  • Assert…= : Подобно директиве что выше (Condition…=), но установленные директивы проверяют различные аспекты рабочей среды, чтобы решить, следует ли активировать устройство. Однако, в отличие от директив Condition…=, отрицательный результат вызывает сбой в этой директиве.

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

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

Из-за этого, только юниты, которые могут быть включены, будут иметь этот раздел. Директивы внутри, говорят что должно произойти, когда устройство включено:

  • WantedBy= : Данная директива, является наиболее распространенным способом определения того, как устройство должно быть включено. Эта директива позволяет вам указать зависимость (аналогично директиве Wants = в разделе ). Разница в том, что эта директива включена в вспомогательную единицу, позволяющую первичному блоку оставаться относительно чистым. Когда устройство с этой директивой определено, то будет создана в системе папка в /etc/systemd/, названная в честь указанного устройства, но с добавлением «.wants» в самом конце. В этом случае будет создана символическая ссылка на текущий блок, создающий зависимость. Например, если текущий блок имеет WantedBy = multi-user.target, каталог с именем multi-user.target.wants будет создан в/etc/systemd/system (если он еще не доступен) и символическая ссылка на текущий блок будут размещены внутри. Отключение этого устройства удаляет связь и удаляет зависимость.
  • RequiredBy= : Эта директива очень похожа на директиву WantedBy =, но вместо этого указывает требуемую зависимость, которая приведет к сбою активации, если не будет выполнена. Когда включено, юнит с этой директивой создаст каталог, заканчивающийся на.requires.
  • Alias= : Эта директива позволяет включить устройство под другим именем. Среди других применений это позволяет доступным нескольким провайдерам функции, чтобы соответствующие подразделения могли искать любого провайдера с общим псевдонимом.
  • Also= : Эта директива позволяет включать или отключать блоки в качестве набора. Здесь можно указать поддерживающие устройства, которые всегда должны быть доступны, когда это устройство активно. Они будут управляться как группа для задач установки.
  • DefaultInstance= : Для template units (более поздних), которые могут создавать экземпляры блоков с непредсказуемыми именами, это может использоваться как резервное значение для имени, если соответствующее имя не предоставляется.

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

Директива Type= может быть одной из следующих:

  • simple : Основной процесс службы указан в стартовой строке. Это значение по умолчанию, если директивы Type= и Busname= не установлены, но установлен ExecStart=. Любое сообщение должно обрабатываться вне устройства через второй блок соответствующего типа (например, через блок.socket, если эта служба должна обмениваться данными с помощью сокетов).
  • forking : Этот тип службы используется, когда служба форкает дочерние процессы при мгновенном покидании родительского процесса. Это сообщает systemd, что процесс все еще работает, даже несмотря на то, что родитель завершил сеанс. Хорошо подходит, например для запуска php-fpm, nginx, tomcat.
  • oneshot : Этот тип указывает, что процесс будет недолговечным и система должна ждать завершения процесса, прежде чем продолжить работу с другими устройствами. Значение по умолчанию для Type= и ExecStart= не установлены. Он используется для одноразовых задач.
  • dbus : Это означает, что устройство будет использовать имя от D-Bus шины. Когда это произойдет, systemd продолжит обработку следующего блока.
  • notify : Это указывает на то, что служба отправит уведомление, когда закончит запуск. Процесс systemd будет ждать, пока это произойдет, прежде чем переходить к другим устройствам.
  • idle : Это означает, что служба не будет запущена до тех пор, пока не будут отправлены все задания.

При использовании определенных типов служб, могут потребоваться некоторые дополнительные директивы. Например:

  • RemainAfterExit= : Эта директива обычно используется с типом onehot. Это означает, что сервис следует считать активным даже после выхода из процесса.
  • PIDFile= : Если тип службы отмечен как «forking», эта директива используется для установки пути файла, который должен содержать идентификационный номер процесса основного «ребенка», который должен контролироваться.
  • BusName= : Эта директива должна быть установлена на имя шины D-Bus, которое служба попытается получить при использовании типа службы «dbus».
  • NotifyAccess= : Эта директива указывает на доступ к сокету, который должен использовать для прослушивания уведомлений при выборе «notify». Она может быть «none», «main» или «all». По умолчанию «none» игнорирует все сообщения о состоянии. «main» вариант будет прослушивать сообщения из основного процесса, а опция «all» приведет к обработке всех членов контрольной группы службы.

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

  • ExecStart= : Нужно указать полный путь и аргументы команды, которая должна быть выполнена для запуска процесса. Это может быть указано только один раз (кроме сервисов «onehot»). Если для пути к команде предшествует символ «-» тире, будут приняты ненулевые статусы выхода без маркировки активации устройства как сбой.
  • ExecStartPre= :Нужно указать полный путь и аргументы команды, которые должны быть выполнены до запуска основного процесса. Это можно использовать несколько раз.
  • ExecStartPost= : Это имеет те же самые качества, что и ExecStartPre = за исключением того, что данная дириктива указывает команды, которые будут запускаться после запуска основного процесса.
  • ExecReload= : Эта необязательная директива указывает команду, необходимую для перезагрузки конфигурации службы, если она доступна.
  • ExecStop= : Это указывает на команду, необходимую для остановки службы. Если это не указано, процесс будет немедленно уничтожен, когда служба будет остановлена.
  • ExecStopPost= : Это можно использовать для указания команд для выполнения после остановке команды.
  • RestartSec= : Если автоматический перезапуск службы включен, это указывает время ожидания перед попыткой перезапуска службы.
  • Restart= : Это указывает на обстоятельства, при которых systemd будет пытаться автоматически перезапустить службу. Она может быть установлена как значения «always», «on-success», «on-failure», «on-abnormal», «on-abort» или «on-watchdog». Это приведет к перезапуску в соответствии с тем, как служба была остановлена.
  • TimeoutSec= : Это устанавливает время, в течение которого система будет ждать остановки службы, прежде чем пометить ее как неудачную или убитую принудительно. Вы можете установить отдельные таймауты с помощью TimeoutStartSec = и TimeoutStopSec =.

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

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

Чтобы указать фактический сокет, эти директивы являются общими:

  • ListenStream= : Это определяет адрес для сокет stream, который поддерживает последовательную, надежную связь. Службы, использующие TCP, должны использовать этот тип сокета.
  • ListenDatagram= : Это определяет адрес для сокет datagram, который поддерживает быстрые, ненадежные пакеты связи. Службы, использующие UDP, должны устанавливать этот тип сокета.
  • ListenSequentialPacket= : Это определяет адрес для последовательной, надежной связи с максимальными дейтаграммами, которые сохраняют границы сообщений. Это чаще всего встречается для Unix сокетов.
  • ListenFIFO : Наряду с другими типами прослушивания вы также можете указать буфер FIFO вместо сокета.

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

Другие характеристики сокетов можно контролировать с помощью дополнительных директив:

  • Accept= : Это определяет, будет ли запущен дополнительный экземпляр службы для каждого соединения. Если установлено значение false (по умолчанию), один экземпляр будет обрабатывать все соединения.
  • SocketUser= : С помощью Unix-сокета задается его владелец. Если не указать, то будет пользователь root.
  • SocketGroup= : С помощью Unix-сокета задается владелец группы. Это будет root группа, если не указано ни то, ни другое. Если установлен только SocketUser =, systemd попытается найти подходящую группу.
  • SocketMode= : Для сокетов Unix или буферов FIFO это устанавливает разрешения для созданного объекта.
  • Service= : Если имя службы не совпадает с именем .socket , эта служба может быть указана с помощью этой директивы.

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

Например, ведущая косая черта (слеш или «/») удаляется, все остальные косые черты переводится в тире «-», и все тире и непечатаемые символы заменяются escape-кодами стиля С. Результат этого перевода используется как имя узла монтирования. Unit-ы монтирования будут иметь неявную зависимость от других монтировок над ней в иерархии.

Mount юниты часто переводятся непосредственно из файла /etc/fstab во время процесса загрузки. Для автоматически созданных определений единиц и те, которые вы хотите определить в единичном файле:

  • What= : Абсолютный путь к ресурсу, который необходимо смонтировать.
  • Where= : Абсолютный путь точки монтирования, в которой должен быть установлен ресурс. Это должно быть таким же, как имя файла устройства, за исключением использования стандартной записи файловой системы.
  • Type= : Тип файловой системы для монтирования.
  • Options= : Любые параметры монтирования, которые необходимо применить. Это список, разделенный запятыми.
  • SloppyOptions= : Логическое значение (0 или 1), которое определяет произойдет ли сбой монтирования, если есть параметр непризнанного монтирования.
  • DirectoryMode= : Если родительские каталоги необходимо создать для точки монтирования, это определяет режим разрешений этих папок.
  • TimeoutSec= : Настраивает время, в течение которого система будет ждать, пока операция монтирования не будет отмечена как сбой.

Этот модуль позволяет автоматически устанавливать подключенный модуль.mount при загрузке. Как и в случае с модулем.mount, эти юниты должны быть названы в честь пути переведенной точки монтирования.

Раздел довольно прост, разрешены только следующие два варианта:

  • Where= : Абсолютный путь automount в файловой системе. Это будет соответствовать имени файла, за исключением того, что вместо перевода используется условное обозначение пути.
  • DirectoryMode= :Если необходимо создать automount или любые родительские каталоги, это определит настройки разрешений для этих компонентов пути.

Swap модули используются для настройки подкачки (свопинга) в системе. Юниты должны быть названы по названию файла или устройства подкачки, используя тот же перенос файловой системы, о котором говорилось выше.

Как и mount параметры, блоки swap могут быть автоматически созданы из /etc/fstab или могут быть сконфигурированы через выделенный unit файл.

Раздел может содержать следующие директивы для конфигурации:

  • What= : Абсолютный путь к местоположению подкачки (будь то файл или устройство).
  • Priority= : Данная опция принимает целое число, которое задает приоритет для настройки подкачки.
  • Options= : Любые параметры, которые обычно задаются в файле /etc/fstab, могут быть установлены с помощью этой директивы. Используется список, разделенный запятыми.
  • TimeoutSec= : Данная опция задает временя, в течение которого, система ожидает активацию своп-а, прежде чем отмечать операцию как зафейленую.

Блок path, определяет путь файловой системы, который systmed может отслеживать изменения. Должен существовать другой блок, который будет активирован, когда определенная активность будет обнаружена в местоположении пути. Активность пути определяется тем, что он не влияет на события.

Раздел может содержать следующие директивы:

  • PathExists= : Эта директива используется для проверки того, существует ли этот путь. Если путь существует, активируется соответствующий блок.
  • PathExistsGlob= : Данная опция такая как и выше, но поддерживает глобальные выражения для определения существования пути.
  • PathChanged= : Данную опцию используют для отслеживания изменений местоположение пути. Связанный блок активируется, если обнаружено изменение (проверяется когда файл закрыт).
  • PathModified= : Данная опция такая как и выше, но активируется при записи файлов, а также когда файл закрыт.
  • DirectoryNotEmpty= : Эта директива позволяет systemd активировать связанный блок, когда каталог больше не пустой.
  • Unit= : Это указывает, что устройство активируется, когда условия пути, указанные выше, выполняются. Если это будет опущено, systemd будет искать файл.service, который имеет то же имя базового юнита, что и этот блок.
  • MakeDirectory= : Данная директива определяет, будет ли systemd создавать структуру каталогов перед просмотром.
  • DirectoryMode= : Если вышеуказанная директива включена, то данная опция установит режим разрешения любых компонентов пути, которые должны быть созданы.

Timer юнит, используются для планирования задач для работы в определенное время или после определенной задержки. Этот тип устройства заменяет или дополняет некоторые функции cron-а и демонов. Должен быть предоставлен соответствующий блок, который будет активирован, когда таймер будет достигнут.

Раздел может содержать некоторые из следующих директив:

  • OnActiveSec= : Эта директива позволяет активировать соответствующий блок относительно активации модуля.timer.
  • OnBootSec= : Эта директива задает время, когда будет активироваться соответствующее устройство после загрузки системы.
  • OnStartupSec= : Эта директива аналогична указанному выше таймеру, но задает когда будет активироваться systemd процесс после загрузки системы.
  • OnUnitActiveSec= : Это устанавливает таймер в зависимости от того, когда последний активировался.
  • OnUnitInactiveSec= : Это устанавливает таймер в отношении того когда unit был неактивный.
  • OnCalendar= : Это позволяет активировать соответствующий блок путем определения абсолютного (вместо относительно).
  • AccuracySec= : Данный юнит используется для установки уровня точности с таймером, который должен быть приклеен. По умолчанию, связанный с ним блок будет активирован в течение одной минуты.
  • Unit= : Эта директива используется для указания того, что необходимо активировать когда таймер истечет. Если не установлены, Systemd будет искать блок с именем.service.
  • Persistent= : Если это установлено, Systemd запустит триггер соответствующего блока.
  • WakeSystem= : Установка этой директивы позволяет «будить систему» из режима ожидания, если таймер будет достигнут.

Раздел на самом деле, не имеет.slice специфической конфигурации. Вместо этого он может содержать некоторые директивы управления ресурсами, которые перечислялись выше.

Хватит теории, перейдем к практике.

Пишем systemd Unit файл

Первое что стоит сделать — так это проверить инициализацию:

# ps -s1| awk "{print $4}"| grep -Ev "CMD"

PS: Вот небольшая статья:

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

[email protected]

Из созданного блока (что выше) можно создать экземпляр др блока, который выглядит следующим образом:

[email protected]

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

Ниже приведены некоторые из наиболее распространенных спецификаторов, которые будут заменены, когда юнит-экземпляра интерпретируется с соответствующей информацией:

  • %n : В любом месте, где это используется, будет добавлено полное имя элемента.
  • %N : Это то же самое, что и выше, но любое экранирование, такое как те, что присутствуют в шаблонах пути файла, будет отменено.
  • %p : Это указывает префикс имени юнита. Это часть названия юнита, которая предшествует символу @.
  • %P : Это то же самое что и выше, но с любым отступлением.
  • %i : Это ссылается на имя экземпляра, которое является идентификатором, следующим за @ в экземпляре. Это один из наиболее часто используемых спецификаторов, поскольку он динамичный. Использование этого идентификатора поощряет использование значимых идентификаторов конфигурации. Например, порт, в котором будет выполняться служба, может использоваться как идентификатор экземпляра, и шаблон может использовать этот спецификатор для настройки спецификации порта.
  • %I : Этот спецификатор такой же, как и выше, но с любым отступлением.
  • %f : Это будет заменено на имя неэкранированного юнита или имя префикса, добавленное к «/».
  • %c : Это будет указывать на управляющую группу устройства со стандартной родительской иерархией /sys/fs/cgroup/ssytemd.
  • %u : Имя пользователя, настроенного для запуска юнита.
  • %U : То же, что и выше, UID вместо имени.
  • %H : Имя хоста системы, на котором выполняется юнит.
  • %% : Это используется для вставки буквенного знака процента.

Используя приведенные выше идентификаторы в шаблоне файла, Systemd заполнит правильные значения при интерпретации шаблона для создания юнит-экземпляра.

Примеры systemd Unit файлов

Рассмотрим следующий пример, — это написания systemd скрипта для запуска tomcat-а. Для этого, открываем файл:

# vim /etc/systemd/system/tomcat9.service

И записываем в него следующий код:

Description=Tomcat9 After=syslog.target network.target Type=forking User=tomcat Group=tomcat Environment=CATALINA_PID=/usr/local/tomcat9/tomcat9.pid Environment=TOMCAT_JAVA_HOME=/usr/bin/java Environment=CATALINA_HOME=/usr/local/tomcat9 Environment=CATALINA_BASE=/usr/local/tomcat9 Environment=CATALINA_OPTS= #Environment="CATALINA_OPTS=-Xms512M -Xmx1024M -server -XX:+UseParallelGC" Environment="JAVA_OPTS=-Dfile.encoding=UTF-8 -Dnet.sf.ehcache.skipUpdateCheck=true -XX:+UseConcMarkSweepGC -XX:+CMSClassUnloadingEnabled -XX:+UseParNewGC -XX:MaxPermSize=128m -Xms512m -Xmx512m" ExecStart=/usr/local/tomcat9/bin/startup.sh ExecStop=/bin/kill -15 $MAINPID WantedBy=multi-user.target

Перезагрузим службу:

# systemctl daemon-reload

Добавим томкат в автозагрузку ОС:

# systemctl enable tomcat9

Перезапускаем томкат:

# systemctl restart tomcat9

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

# systemctl status tomcat9 ● tomcat9.service - Tomcat9 Loaded: loaded (/etc/systemd/system/tomcat9.service; enabled) Active: active (running) since Tue 2017-05-09 22:04:58 EEST; 6s ago Process: 28528 ExecStop=/bin/kill -15 $MAINPID (code=exited, status=0/SUCCESS) Process: 28531 ExecStart=/usr/local/tomcat9/bin/startup.sh (code=exited, status=0/SUCCESS) Main PID: 28541 (java) CGroup: /system.slice/tomcat9.service └─28541 /usr/bin/java -Djava.util.logging.config.file=/usr/local/tomcat9/conf/logging.properties -Djava.ut... May 09 22:04:58 debian systemd: Starting Tomcat9... May 09 22:04:58 debian startup.sh: Tomcat started. May 09 22:04:58 debian systemd: Started Tomcat9.

Как видим, все четко работает. На этом, у меня все! Больше примеров будет дальше. Я буду добавлять их по мере необходимости. Но в основном, я использую шаблон что выше (только немного его видоизменяю).

Статья «Пишем systemd Unit файл» завершена.

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

Systemd: быстрее света

Схема загрузки типичного Linux-дистрибутива выглядит примерно так: ядро инициализирует железо и запускает процесс /sbin/init, который, в свою очередь, запускает инициализационные скрипты. Скрипты монтируют файловые системы, настраивают сеть, различные устройства и начинают последовательный запуск демонов: syslogd, cron, cups и прочих, которые перечислены в конфигурационных файлах. В самом конце init запускает менеджер входа в систему: getty или xdm (kdm, gdm). Просто и логично, не так ли? Однако такая схема довольно примитивна, а в сравнении с Windows и Mac OS X так и вообще архаична. Их системы инициализации запускают задачи параллельно, не дожидаясь завершения одной, чтобы передать управление следующей. Если одна из них застопоривается на операции ввода-вывода, управление сразу получает другая, так что общее время загрузки сокращается, да так существенно, что традиционная система оказывается далеко позади.

В мире Linux так ведет себя только Ubuntu, да и то только последние два года. Все остальные продолжают по старинке последовательно грузить систему или используют самосборные костыли, которые распараллеливают процесс загрузки неумело и часто ошибочно (Gentoo и Arch, привет!). По-настоящему универсальное решение не найдено до сих пор, поэтому над идеей параллельной системы инициализации работают многие программисты.

Леннарт Поттеринг, сотрудник Red Hat и автор PulseAudio, один из них. Его последнее достижение - демон systemd, очередной претендент на звание убийцы /sbin/init, мимо которого можно было бы спокойно пройти, если бы идея, заложенная в его основу, не оказалась столь интересной и правильной.

Systemd отличается от любой другой системы инициализации тем, что намеренно делает сложные вещи простыми. 99% всех остальных параллельных систем инициализации провалились просто потому, что в сравнении с простым и понятным даже дикарю /sbin/ init они выглядели тяжеловесными монстрами. Чтобы обеспечить возможность параллельного запуска, не введя ОС в противоречивое состояние (которое может возникнуть, если, например, пытаться настроить сеть до загрузки сетевых драйверов или запустить демоны, не смонтировав нужную ФС), использовались различные методы синхронизации. В основном это были своеобразные «метки зависимостей», которые не давали очередному шагу инициализации отработать, если не был пройден шаг, описанный в его зависимостях.
Например, cron зависит от syslog, потому что ему надо вести логи; syslog зависит от настойки сети, потому что он способен принимать логи от удаленных машин и так далее. Из-за этого инициализационные скрипты превращались в запутанную вереницу блоков, а их составление значительно усложнялось. Systemd организован намного проще, он не следит за зависимостями, а просто запускает все, что есть, одновременно.

Я не шучу. Systemd использует механизмы контроля зависимостей только на самых ранних этапах инициализации, которые так или иначе должны происходить последовательно (монтирование корневой файловой системы, подключение swap, загрузка модулей и так далее). Когда же дело доходит до демонов, на запуск которых уходит 90% всего времени инициализации ОС, systemd забывает о зависимостях и стартует их всех сразу, показывая просто потрясающую скорость.

Это работает благодаря тому, что systemd знает об особенности работы демонов и их связи между собой.

Ведь на самом деле демонам нужны вовсе не другие демоны, а только «коммуникационные каналы», обеспечивающие обмен данными: cron не зависит от syslog, ему нужен сокет /dev/log, в который он сможет записывать свои логи, это же справедливо и в отношении любого другого демона. Все они общаются через сокеты, и единственная причина, почему демон A должен быть запущен раньше демонов B, C и D, заключается в том, что демон A должен создать сокет, который им нужен. Systemd учитывает эту особенность, поэтому его механизм параллельного запуска основан на сокетах, которые он создает для каждого демона заблаговременно, а затем запускает демоны одновременно. При этом ответственность за синхронизацию и «отслеживание зависимостей» теперь перекладываются на ядро, в рамках которого и реализован механизм сокетов.

Если, например, cron получит управление раньше syslog, ничего страшного не произойдет - cron найдет свой любимый /dev/log и даже сможет писать в него сообщения (если захочет, конечно), которые будут, нет, не выброшены, а буферизированы в сокете, но только до тех пор, пока cron не захочет записать в сокет сообщение, способное его переполнить. В этом случае ядро заблокирует процесс cron и передаст управление следующему процессу в очереди на исполнение (следующему демону). Вскоре (а может быть и сразу) очередь дойдет и до syslog, который запустится, прочитает сообщения, скопившиеся в /dev/log, обработает их и сам на чем-нибудь заблокируется (либо истратит отведенное ему время), и управление перейдет следующему демону. Типичная многозадачность без лишних костылей.

Более того, благодаря такой схеме большинство демонов могут быть запущены только тогда, когда в них возникнет реальная необходимость. Так, например, CUPS вовсе не обязательно запускать во время инициализации ОС, когда нагрузка на систему и без того высока. Логичнее стартануть его, когда на печать будет отправлен первый документ. Systemd позволяет сделать такое, следя за активностью вокруг сокетов, и применяет похожий подход для монтирования файловых систем, подключая их к точкам монтирования только при попытке получить доступ к файлам (также демоны могут быть запущены при появлении в системе определенного файла-устройства).

Справедливости ради стоит сказать, что столь гениальное решение проблемы зависимостей было придумано и реализовано в Mac OS X с самого начала ее существования, но до автора systemd почему-то никто не обращал на это внимания.

Кстати, у самого systemd есть другая и явно уникальная для Linux характеристика: он умеет группировать процессы с помощью cgroups с установкой различных лимитов среды исполнения на всю группу (ограничения ресурсов, рабочий и корневой каталоги, umask, настройки OOM killer, параметр nice, приоритет операций ввода-вывода, приоритеты использования процессора и многое другое). То есть демонов теперь можно помещать в виртуальные окружения без использования какого бы то ни было дополнительного ПО, просто прописав в файл настроек systemd несколько строк.

Systemd уже доступен для скачивания и возможно будет включен в один из будущих релизов Fedora в качестве альтернативной системы инициализации. Инструкции по установке в другие дистрибутивы можно найти на официальной страничке: freedesktop.org/wiki/Software/systemd .

Установить Systemd в Ubuntu можно, выполнив следующие команды:

$ sudo add-apt-repository ppa:andrew-edmunds/ppa
$ sudo apt-get update
$ sudo apt-get install systemd

Далее следует отредактировать /boot/grub/grub.cfg, добавив к параметрам ядра строчку init=/sbin/systemd. После перезагрузки дистрибутив будет работать с новой системой инициализации, в чем можно убедиться с помощью команды:

$ sudo systemctl units-list

Для проверки состояния, запуска, остановки и включения служб используются аргументы status, start, stop и enable.

Ulatencyd: мгновенная реакция

Какой, на твой взгляд, самый важный параметр десктопной операционной системы? Хороший графический интерфейс? Количество доступных приложений? Простота использования?

Да, все это имеет значение, но сегодня, когда этими свойствами легко наделить даже серверные ОС, решающими становятся совсем другие факторы, важнейший из которых - отзывчивость системы.

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

Для разработчиков операционных систем это прописная истина, поэтому во все времена они стремились сделать свои ОС более интерактивными. У одних это получалось хорошо (привет BeOS), у других плохо (куда же без MS), но были и такие, у кого это не получалось вообще. Долгое время разработчики Linux совершенно не интересовались темой отзывчивости Linux на десктопах. Кон Коливас множество раз указывал им на проблемы, говорил о неповоротливости и медлительности Linux, писал патчи, ночами кодил новые планировщики задач, добивался их включения в ядро. Все напрасно, раз за разом патчи отвергали, а самого автора грубо отстраняли от дел.

Однако со временем труды Кона Коливаса окупились. Инго Молнар начитался его исходников и написал планировщик CFS (Completely Fair Scheduler), а Линукс незамедлительно включил его в ядро 2.6.23. После этого положение дел на десктопах существенно улучшилось, и Linux стал намного быстрее (при этом реализация Кона все равно продолжала показывать более впечатляющие результаты).

Второй важной вехой на пути Linux к десктопу стало включение знаменитого 200-страничного патча в ядро 2.6.38, а также появление его аналога на языке bash. Так Linux научился отделять интерактивные процессы от всех остальных демонов, серверов и bash-скриптов и наделять их более высокими приоритетами. Это событие еще больше улучшило ситуацию и сделало ее практически идеальной: теперь Linux не тормозил даже тогда, когда в фоне шла пересборка ядра в несколько потоков.
Наконец, третьим важным шагом для десктопного Linux (здесь я подхожу к самому главному) стало появление демона ulatencyd, способного регулировать отзывчивость системы динамически, подстраивая ее под изменяющиеся обстоятельства.

Как и ядерный патч, ulatencyd использует механизм cgroups для группировки интерактивных процессов и изменения их приоритетов, но на этом его работа не заканчивается. Демон использует эвристические алгоритмы для выявления «наиболее интерактивных» процессов, а также явных вредителей системы, таких как форк-бомбы и программы с большими утечками памяти. При этом первые получают еще больший приоритет, а вторые жестко урезаются в возможностях (получая низкий приоритет, ограничения на доступную память), изолируются или уничтожаются. Но что самое главное, в любой момент демон можно обучить новым правилам отбора процессов, так что мы теперь можем назначать самые высокие (даже реалтаймовые) приоритеты любимым играм, видеоплеерам и браузерам.

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

Чтобы установить ulatencyd, необходимо скачать его исходники со страницы и собрать с помощью стандартных cmake и make:

$ cmake
$ make
$ sudo make install

$ sudo /usr/local/sbin/ulatencyd -v 2

И понаблюдать за тем, как он группирует процессы по приоритетам:

$ ps xaf -eo pid,session,args,cgroup

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

relayd: по трем фронтам

Какая связь между мониторингом сетевых хостов, балансировкой нагрузки и прокси-сервером? Все это функции одной машины? Да, вполне возможно. Но что если я скажу, что все эти три функции тесно связаны между собой и должны быть реализованы в рамках одного универсального приложения? Бред? Никак нет.

Возьмем, к примеру, достаточно распространенную в узких кругах функцию сервера под названием «распределение нагрузки между несколькими DNS-серверами». Что нужно для ее решения? Во-первых, умение перенаправлять DNS-трафик на другой хост (от балансировщика к одному из реальных DNS-серверов).

Это можно сделать с помощью брандмауэра или особым образом настроенного BIND (несколько тяжеловесный вариант). Вовторых, умение выбирать наиболее подходящего кандидата для обработки запроса из списка DNS-серверов. Это уже сложнее, и здесь может понадобиться специализированное ПО или опять же брандмауэр (но очень хороший). В-третьих, умение проверять DNS-сервера на доступность и удалять упавших из списка. Нужен скрипт, пингующий хосты и управляющий списками, либо особые возможности брандмауэра (а такой есть?). В общем, долгое нудное велосипедостроение или покупка специализированного решения для конкретной задачи по нереальным ценам. А что если завтра вдруг понадобится сделать нечто подобное для SMTP?

Все править или вновь открывать кошелек? Не стоит, содержимое кошелька все-таки лучше приберечь, а костыли с велосипедами оставить спортсменам. Демон relayd, появившийся в OpenBSD 4.3, позволяет решить эту и еще огромное количество других, подобных и не очень, задач всего за несколько минут.

Он включает в себя возможности балансировщика нагрузки для протоколов уровней 3, 4 и 7, прокси уровня 7 (релей) и сервиса проверки доступности сетевых узлов (из которого и вырос).

На основе relayd можно строить самые разные конфигурации, начиная от простых прокси-серверов или SSL-акселераторов и заканчивая сложными решениями вроде прозрачных web-прокси с фильтрацией запросов и распределением нагрузки между несколькими web-серверами. И все это с помощью простого конфигурационного файла, длина которого даже в самых сложных конфигурациях редко превышает 50 строк.

Да, конечно, без примера все это только слова. Так что вот рабочий конфиг, полностью удовлетворяющий требованиям, выдвинутым в начале раздела:

# vi /etc/relayd.conf

Переменные и макросы

Адрес и порт нашего релея

relayd_addr="127.0.0.1"
relayd_port="8053"

Адреса трех DNS-серверов, которые будут обрабатывать

запросы

table { 192.168.1.1, 192.168.1.2, 192.168.1.3 }

Общие настройки

Интервал между проверками хостов на доступность

(10 секунд)

Таймаут для проверки хостов на доступность методом TCP

(если хост не отвечает дольше 200 мс - он в дауне)

Разделяем сервер на 5 процессов для более эффективной

обработки запросов

Логировать результаты проверки хостов на доступность

Настройки DNS-протокола

Параметры оптимизации соединения

dns protocol "dnsfi lter" { tcp { nodelay, sack, socket buffer 1024, backlog 1000 } }

Настройки релея

relay dnsproxy {

Прослушиваемый адрес и порт

listen on $relayd_addr port $relayd_port

Работаем с описанным ранее протоколом

protocol "dnsfi lter"

Оправляем DNS-пакеты одному из перечисленных в таблице

DNS-серверов, предварительно проверив его на доступность

forward to port 53
mode loadbalance check tcp
}

Наиболее важные части этого конфига находятся в теле директив dns protocol и relay. Первая представляет собой нечто вроде шаблона, который используется для того, чтобы не повторять одни и те же настройки протоколов в других частях конфигурационного файла (relayd поддерживает три протокола: HTTP, DNS и TCP). Вторая - это настройка релея, в котором указаны прослушиваемый порт, проксируемый протокол, его настройки и информация о том, каким образом и какому хосту должны быть перенаправлены пакеты. В нашем случае прокси должен отправить DNS-запрос одному из трех серверов с предварительной проверкой на доступность (здесь используется проверка методом TCP-рукопожатия, но relayd поддерживает множество других методов, начиная от ping и заканчивая попыткой установить SSLсоединение). При этом, если один из DNS-серверов окажется в дауне, relayd автоматически исключит его из списка до тех пор, пока плановая проверка на доступность (интервал между проверками указан в опции interval) не покажет его работоспособность.

Для тестирования конфигурации можно использовать следующую форму запуска relayd:

# relayd -d -vv -f /etc/relayd.conf

Так демон не уйдет в фон и будет вести подробную распечатку всех своих действий. После отладки конфигурации можно настроить запуск демона во время загрузки системы. Для этого достаточно поместить строку relayd_flags=»» в файл /etc/rc.conf.local.

FreeBSD fscd: красота минимализма

Этого раздела не должно было быть в статье. Демон fscd настолько простой инструмент, что писать о нем отдельно мне казалось излишним. С другой стороны, не писать о нем нельзя, потому как это один из ярчайших примеров правильного решения задачи в стиле UNIX. А задача у разработчиков FreeBSD была следующая.
Различные системные и не очень демоны могут время от времени падать (или начинать вести себя как идиоты, что еще хуже). На домашней машине это не страшно, упавшего можно перезапустить руками или отправить комп в перезагрузку. Но что делать на сервере, где админ бывает редко?

Сервисы надо мониторить и перезапускать по мере необходимости. Как это сделать? Естественно, встроить эту функциональность в систему инициализации (ведь именно она занимается запуском демонов). И, например, в Solaris так и сделано, да настолько экстравагантно, что сам Линус Торвальдс ногу сломит, пока разберется с его настройкой. Разработчики FreeBSD поступили проще. Они написали отдельный демон, который способен работать со скриптами инициализации FreeBSD, оставаясь совершенно независимой системой. Вся соль в том, что fscd получился настолько простым, что им можно пользоваться, не читая man-страниц и не беспокоясь о том, что он может упасть. Посуди сам, чтобы заставить fscd следить за, например, sshd, нужно ввести всего одну команду:

# fscadm enable sshd /var/run/sshd.pid

Все, fscd запомнит этот выбор и автоматически включит мониторинг после перезагрузки машины. Единственное условие: у подконтрольного демона должен быть инициализационный файл в каталоге /etc/rc.d (или /usr/local/etc/rc.d) и запись в файле /etc/rc.conf, включающая его (это очевидно).

Демон fscd будет доступен только во FreeBSD 9.0, но его вполне можно скачать с официальной странички (people.freebsd.org/~trhodes/fsc) и собрать для восьмерки.

Выводы

Каждый день в мире UNIX появляется что-то новое, но очень редко это новое оказывается чем-то стоящим нашего внимания. В этой статье я рассказал о четырех системных компонентах UNIX, которые не только заслуживают особого внимания, но и несут реальную пользу. Кто знает, возможно в будущем они будут такой же неотъемлемой частью UNIX, как команда grep или демон syslog.

Links

  • дом systemd под крылом: freedesktop.org/wiki/Software/systemd ; freedesktop.org
  • исходные тексты systemd: cgit.freedesktop.org/systemd ;
  • код ulatencyd: github.com/poelzi/ulatencyd ;
  • исходники fscd: people.freebsd.org/~trhodes/fsc .

Info

  • В долгосрочной перспективе автор собирается превратить systemd в полноценный менеджер сессий, способный заменить gnomesession и kdeinit.
  • Кроме всего прочего, systemd обладает функциями монитора для демонов, так что возможности fscd встроены в него от рождения.
  • Отказ от использования скриптов - один из методов ускорить процесс загрузки. Многие задачи инициализации systemd способен произвести через прямой вызов нужных команд, без использования скриптов.
  • Прежнее название relayd - hostated (от слов host state, «состояние хоста»), было изменено на теперешнее в связи с расширением функционала.

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).

Понадобилось на днях написать простой bash-скрипт, для постоянного мониторинга каталога на наличие в нем файлов *.pdf, с последующей их конвертацией в формат txt. Скрипт должен был работать в фоновом режиме и автоматически запускаться при перезагрузке.

Для реализации работы в фоне сначала написал Linux - демон на C, но потом решил что для моей задачи это слишком, и реализовал это при помощи Systemd.

Для начала нужно убедиться, что ваш дистрибутив работает с Systemd, командой:

readlink /proc/1/exe
если вывод будет /sbin/init - то у вас используется SysV, и вам нужно либо обновить дистрибутив, как в моем случае, я обновил Debian 7 Wheezy до Debian 8 Jessie, либо реализовать работу в фоновом режиме другим способом.

Если вывод такой:
/lib/systemd/systemd - то все в порядке, у вас Systemd.

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

/run/systemd/system/ - юниты, созданные в рантайме. Этот каталог приоритетнее каталога с установленными юнитами из пакетов.
/etc/systemd/system/ - юниты, созданные и управляемые системным администратором. Этот каталог приоритетнее каталога юнитов, созданных в рантайме. В этом каталоге мы и будем создавать свой юнит.

Переходим в каталог /etc/systemd/system/ и создаем в нем, либо копируем какой-либо существующий файл, к примеру sshd.service, и в нем пишем:

    [ Unit]

    Description =MyBashScript

    After =syslog.target

  1. [ Service]

  2. ExecStart =/ bin/ bash "/home/user/scripts/script.sh"

    Type =forking

  3. [ Install]

    WantedBy =multi-user.target

    Alias =bash.service

Подробнее о каждой секции:
Секция :
Содержит общую информацию о сервисе, его описание, и то, что он должен стартовать после запущенного демона Syslog.

Секция
Непосредственная информация о нашем сервисе.
Параметр ExecStart указывает на исполняемый файл нашего сервиса. Нужно указывать абсолютные пути, в случае с bash-скриптом путь до скрипта берем в одинарные кавычки.
Type=forking означает, что запускаемый скрипт будет работать в режиме демона. Если мы хотим, чтобы скрипт выполнился один раз, то указываем Type=simple.

Секция
Последняя секция содержит информацию о цели, в которой сервис должен стартовать. В данном случае мы хотим, что сервис должен быть запущен, когда будет активирована цель multi–user.target (это аналог init 3 в SysV).
Alias=bash.service - для удобства создадим алиас, чтобы проще управлять нашим сервисом через systemctl.

Это работающий файл сервиcа Systemd, с небольшим функционалом. Сохраняем файл, и выполняем команду systemctl daemon-reload , чтобы Systemd узнал о нашем сервисе, и вы могли его запустить командой systemctl start bash.service .
У меня запустить получилось не с первого раза, так как сначала я указал не абсолютный путь в параметре ExecStart секции . После исправления Systemd все равно ругался на ту же ошибку, помогла перезагрузка.

Для просмотра состояния, старта, остановки, перезагрузки, включения или выключения системных сервисов используется команда systemctl . В более ранних версиях Systemd использовались команды service и chkconfig, они по прежнему включены в систему, в основном для обратной совместимости.

Ниже представлены основные команды systemctl:

systemctl start name.service – запуск сервиса.
systemctl stop name.service - остановка сервиса
systemctl restart name.service - перезапуск сервиса
systemctl try-restart name.service - перезапуск сервиса только, если он запущен
systemctl reload name.service - перезагрузка конфигурации сервиса
systemctl status name.service - проверка, запущен ли сервис с детальным выводом состояния сервиса
systemctl is-active name.service - проверка, запущен ли сервис с простым ответом: active или inactive
systemctl list-units --type service --all – отображение статуса всех сервисов
systemctl enable name.service – активирует сервис (позволяет стартовать во время запуска системы)
systemctl disable name.service – деактивирует сервис
systemctl reenable name.service – деактивирует сервис и сразу активирует его
systemctl is–enabled name.service – проверяет, активирован ли сервис
systemctl list-unit-files --type service – отображает все сервисы и проверяет, какие из них активированы
systemctl mask name.service – заменяет файл сервиса симлинком на /dev/null, делая юнит недоступным для systemd
systemctl unmask name.service – возвращает файл сервиса, делая юнит доступным для systemd

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 соответственно).