Если вы уже знакомы с тем, как работают утилиты наподобие inetd, xinetd и automount, вы увидите много сходного. Действительно, сама концепция не нова (и в действительности команда systemd включает поддержку модулей automount). Мы перейдем к примеру модуля сокета в пункте «Пример модуля сокета и службы» далее. Однако сначала рассмотрим, какую помощь оказывают модули ресурсов при загрузке системы.
Оптимизация загрузки и вспомогательные модули
При обычном способе активизации модулей в команде systemd предпринимаются попытки упростить порядок следования зависимостей и ускорить время загрузки системы. Это напоминает запуск по запросу тем, что модуль службы и вспомогательный модуль представляют ресурс, предлагаемый модулем службы, только в данном случае команда systemd запускает модуль службы, как только она активизирует вспомогательный модуль.
В основе данной схемы лежит то, что таким важным модулям служб времени загрузки, как syslog и dbus
На рис. 6.2 показано, как такая схема могла бы работать в традиционной системе. В данной последовательности загрузки служба E предоставляет важный ресурс R. Службы A, B и C зависят от этого ресурса и должны ожидать запуска службы E. Во время загрузки такой системе потребуется довольно много времени, чтобы добраться до запуска службы С.
Рис. 6.2. Временн'aя последовательность загрузки. Указана зависимость ресурсов
На рис. 6.3 показана эквивалентная конфигурация загрузки с помощью команды systemd. Службы представлены модулями A, B и C, а новый модуль R представляет ресурс, который предоставляет модуль E. Поскольку команда systemd способна обеспечить интерфейс для модуля R, пока запускается модуль E, модули A, B, C и E могут быть все запущены одновременно. Модуль E заступает на место модуля R, когда будет готов. Интересным моментом здесь является то, что модулям A, B и C может не понадобиться явный доступ к модулю R до завершения их запуска — это демонстрирует на схеме модуль B.
примечание
При подобном распараллеливании запуска есть вероятность того, что система на некоторое время замедлит свою работу вследствие большого количества одновременно стартующих модулей.
В конечном счете, хотя вы и не создаете в данном случае запуск модуля по запросу, вы используете те же функции, которые делают его возможным. Чтобы увидеть примеры из реальной жизни, загляните в модули конфигурации syslog и D-Bus на компьютере, использующем команду systemd; очень возможно, что они будут распараллелены подобным же образом.
Пример модуля сокета и службы
Рассмотрим теперь в качестве примера простую службу сетевого эхо-запроса, которая использует модуль сокета. Этот материал достаточно сложный, и вы, вероятно, сможете понять его только после прочтения глав 9 и 10, в которых рассмотрены протокол TCP, порты, прослушивание и сокеты. По этой причине сейчас можно его пропустить и вернуться к нему позже.
Рис. 6.3. Временн'aя последовательность загрузки с помощью systemd и модуля ресурсов
Идея, заложенная в эту службу, заключается в том, что, когда сетевой клиент подключается к данной службе, она повторяет все, что отправляет клиент. Модуль будет прослушивать TCP порт 22222. Мы назовем его службой эхо-запроса и начнем с модуля сокета, представленного следующим файлом модуля echo.socket:
[Unit]
Description=echo socket
[Socket]
ListenStream=22222
Accept=yes
Обратите внимание на то, что внутри файла модуля нет упоминания о том, какой модуль службы поддерживается данным сокетом. Каков же тогда соответствующий файл модуля службы?
Он называется echo@.service. Эта ссылка составлена на основе соглашения о присвоении имен: если у файла модуля службы такой же префикс, что и у файла .socket (в данном случае echo), команда systemd знает о том, что надо активизировать данный модуль службы, когда в модуле сокета возникает активность. В данном случае команда systemd создает экземпляр echo@.service, когда возникает активность сокета echo.socket.
Вот файл модуля службы echo@.service:
[Unit]
Description=echo service
[Service]
ExecStart=-/bin/cat
StandardInput=socket
примечание
Если вам не нравится неявная активизация модулей на основе префиксов или же вам необходимо создать механизм активизации между двумя модулями с разными префиксами, можно использовать вариант явного присвоения в модуле, который определяет ресурс. Применяйте, например, запись Socket=bar.socket внутри файла foo.service, чтобы модуль bar.socket предоставлял свой сокет службе foo.service.
Чтобы данная служба заработала, необходимо запустить после нее сокет echo.socket: