Вопрос или проблема
У меня есть программа, которая при обычной активации слушает на некотором порту.
Я не хочу, чтобы программа работала непрерывно.
Есть ли «быстрый и грязный» способ обернуть приложение в оболочку или что-то подобное, что будет мониторить соответствующий порт и запускать сервис по запросу?
Самый простой подход, вероятно, приведет к сбою соединения, так как оболочка должна будет освободить порт, а затем запустить приложение. Однако, если клиент просто подключится снова через короткое время, то это все может сработать.
Но, конечно, было бы еще лучше, если бы это было полностью прозрачно для клиента.
Как уже упомянул richard, то, что вы ищете, существует уже давно. Это называется inetd.
Существует несколько реализаций inetd. Некоторые из них просты и делают только это — активацию сокетов (чаще всего это просто программа inetd
из некоторого более крупного программного пакета, содержащая другие основные сетевые инструменты, такие как GNU inetutils или BusyBox, или инструменты BSD, которые были портированы на Linux), некоторые предлагают больше функций (xinetd довольно популярен, rlinetd описывает себя как «ужасно перегруженный функциями»), и существует реализация inetd в systemd (что только не реализует systemd?).
Практически каждая система Unix поставляется с реализацией inetd. Традиционно «малые» сервисы, такие как echo, finger, ftp и т.д., использовали inetd, в то время как «большие» сервисы, такие как httpd и NFS, а также помощники, такие как ssh, не использовали. Используйте реализацию inetd по умолчанию в вашей дистрибутиве, если вам не нужно больше, чем базовый сервис.
Также возможно попросить systemd открыть сокет (будь то TCP, UDP или unix AF) и затем запустить сервис, когда будет получено соединение. Поскольку не все сервисы довольны тем, что им передаются существующие сокеты и предпочитают создавать свои собственные, systemd также включает помощник под названием systemd-socket-proxyd, который буферизует содержимое на открытом сокете до тех пор, пока требуемый сервис не выйдет в онлайн с правильным слушающим сокетом.
Ответ или решение
Чтобы начать службу на запрос сети, используя активацию сокетов, вы можете использовать систему systemd
, которая поддерживает эту функциональность. Это избавит вас от необходимости писать собственный скрипт для мониторинга порта. Вместо этого systemd
будет автоматически запускать вашу программу, когда поступает соединение на определённый порт.
Вот пошаговая инструкция, как это сделать:
Шаг 1: Создание службы
Сначала создайте файл службы для вашего приложения в каталоге /etc/systemd/system/
. Предположим, что ваше приложение называется myservice
, и вы хотите запускать его, когда поступает соединение на порту 12345
. Создайте файл myservice.service
со следующим содержимым:
[Unit]
Description=My Service
[Service]
ExecStart=/path/to/your/application
Restart=on-failure
[Install]
WantedBy=multi-user.target
Шаг 2: Создание сокета
Теперь создайте файл сокета в /etc/systemd/system/
, который будет отвечать за активацию вашей службы при получении соединения. Назовите его, например, myservice.socket
:
[Unit]
Description=My Service Socket
[Socket]
ListenTCP=12345
[Install]
WantedBy=sockets.target
Шаг 3: Активация службы и сокета
Теперь вам нужно активировать новый сокет и службу. Вы можете сделать это с помощью следующих команд:
sudo systemctl enable myservice.socket
sudo systemctl start myservice.socket
Эти команды настроят сокет для автоматического запуска при загрузке системы и запустят его прямо сейчас.
Шаг 4: Проверка работы
Теперь ваше приложение должно автоматически запускаться при первом соединении на порт 12345
. Вы можете проверить статус сокета и службы с помощью:
sudo systemctl status myservice.socket
sudo systemctl status myservice.service
Дополнительные замечания
-
buffering (буферизация): Если ваше приложение не принимает существующие сокеты (например, если он не может работать с переданным сокетом), убедитесь, что система в состоянии корректно буферизовать данные. В этом случае может быть полезен
systemd-socket-proxyd
. -
Логирование: Проверьте логи вашего приложения и службы с помощью
journalctl -u myservice.service
, чтобы убедиться, что оно запускается и обрабатывает запросы корректно.
Используя эту схему, вы получите прозрачное для клиента решение: при первом запросе на порт ваша программа будет запускаться, и клиент не заметит никакой задержки, если соединение будет немедленно инициировано.