На рис. 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. Временнáя последовательность загрузки с помощью systemd и модуля ресурсов
Идея, заложенная в эту службу, заключается в том, что, когда сетевой клиент подключается к данной службе, она повторяет все, что отправляет клиент. Модуль будет прослушивать TCP порт 22222. Мы назовем его службой эхо-запроса и начнем с модуля сокета, представленного следующим файлом модуля echo.socket:
[Unit]
Description=echo socket
[Socket]
ListenStream=22222
Accept=yes
Обратите внимание на то, что внутри файла модуля нет упоминания о том, какой модуль службы поддерживается данным сокетом. Каков же тогда соответствующий файл модуля службы?
Он называется [email protected]. Эта ссылка составлена на основе соглашения о присвоении имен: если у файла модуля службы такой же префикс, что и у файла. socket (в данном случае echo), команда systemd знает о том, что надо активизировать данный модуль службы, когда в модуле сокета возникает активность. В данном случае команда systemd создает экземпляр [email protected], когда возникает активность сокета echo.socket.
Вот файл модуля службы [email protected]:
[Unit]
Description=echo service
[Service]
ExecStart=-/bin/cat
StandardInput=socket
примечание
Если вам не нравится неявная активизация модулей на основе префиксов или же вам необходимо создать механизм активизации между двумя модулями с разными префиксами, можно использовать вариант явного присвоения в модуле, который определяет ресурс. Применяйте, например, запись Socket=bar.socket внутри файла foo.service, чтобы модуль bar.socket предоставлял свой сокет службе foo.service.
Чтобы данная служба заработала, необходимо запустить после нее сокет echo.socket:
# systemctl start echo.socket
Теперь можно проверить эту службу, подключившись к локальному порту 22222. Когда приведенная ниже команда telnet установит соединение, наберите что-либо и нажмите клавишу Enter. Служба возвратит вам набранный текст.
$ telnet localhost 22222
Trying 127.0.0.1…
Connected to localhost.
Escape character is '^]'.
Hi there.
Hi there.
Когда захотите закончить, нажмите сочетание клавиш Ctrl+] в самой строке, а затем сочетание клавиш Ctrl+D. Чтобы остановить службу, остановите модуль сокета:
# systemctl stop echo.socket
Экземпляры и передача управления
Поскольку модуль [email protected] поддерживает несколько одновременных экземпляров, в его имени присутствует символ @ (вспомните, что такой символ означает параметризацию). Однако зачем может понадобиться несколько экземпляров? Причина в том, что у вас может оказаться более одного сетевого клиента, подключенного к этой службе в данный момент времени, и каждое соединение должно иметь собственный экземпляр.
В указанном случае модуль службы должен поддерживать несколько экземпляров, поскольку в файле echo.socket есть параметр Accept. Этот параметр указывает команде systemd, чтобы она не только прослушивала порт, но и принимала входящие соединения, а затем передавала входящие соединения модулю службы, создавая для каждого соединения отдельный экземпляр. Каждый экземпляр считывает данные из соединения как стандартный ввод, но при этом экземпляру не обязательно знать о том, что эти данные исходят из сетевого соединения.
примечание