SystemdDoctor
служба не работает сокеты сокет-активация

Служба не получает сокет при сокет-активации

При сокет-активации systemd открывает адрес сам и передаёт готовый дескриптор службе начиная с номера 3, сообщая их количество в переменных LISTEN_FDS и LISTEN_PID. Если служба этого не ожидает или имена unit не совпадают, она пытается открыть порт сама — и получает отказ или работает не через сокет.

Вероятные причины

По порядку: сверху то, что встречается чаще.

  1. Программа не умеет принимать готовый дескриптор

    Сокет-активация требует поддержки со стороны программы. Без неё служба просто откроет свой порт, а сокет systemd останется незадействованным — или займёт порт первым.

  2. Имена сокета и службы не совпадают

    По умолчанию myapp.socket активирует myapp.service. При других именах нужен параметр Service= в сокете.

  3. Указан Accept=yes, а служба ждёт слушающий сокет

    При Accept=yes systemd принимает соединение и запускает отдельный экземпляр службы на каждое, передавая уже установленное соединение. Обычной сетевой службе нужен Accept=no.

  4. Служба ищет дескриптор по имени, а имя не задано

    Программы, работающие с несколькими сокетами, различают их по именам из FileDescriptorName=. Без имени они не находят нужный.

Диагностика

Команды идут в том порядке, в котором их стоит выполнять: каждая следующая проверяет то, что осталось после предыдущей.

Показывает адрес, сокет и активируемую им службу — сразу видно расхождение имён.

systemctl list-sockets --no-pager

Три параметра, от которых зависит передача дескриптора.

systemctl show myapp.socket -p Accept -p Service -p FileDescriptorName

Журналы сокета и службы вместе: видно порядок событий при активации.

journalctl -u myapp.socket -u myapp.service -n 40 --no-pager

Решение

Решение своё для каждой причины. Сначала определите, какая из них ваша, — иначе правки наложатся друг на друга.

1. Программа не умеет принимать готовый дескриптор
Почему происходит
Сокет-активация требует поддержки со стороны программы. Без неё служба просто откроет свой порт, а сокет systemd останется незадействованным — или займёт порт первым.
Как проверить
Посмотрите, что делает служба при запуске, и переменные окружения.
systemctl show myapp.service -p Sockets
sudo ss -tlnp | grep 8080
Как исправить
Либо откажитесь от сокет-активации и пусть служба слушает сама, либо используйте программу, которая поддерживает передачу дескрипторов.
2. Имена сокета и службы не совпадают
Почему происходит
По умолчанию myapp.socket активирует myapp.service. При других именах нужен параметр Service= в сокете.
Как проверить
Посмотрите, какую службу активирует сокет.
systemctl show myapp.socket -p Service
systemctl show myapp.service -p Sockets
Как исправить
Укажите связь явно параметром Service= в секции [Socket].
[Socket]
Service=backend.service
3. Указан Accept=yes, а служба ждёт слушающий сокет
Почему происходит
При Accept=yes systemd принимает соединение и запускает отдельный экземпляр службы на каждое, передавая уже установленное соединение. Обычной сетевой службе нужен Accept=no.
Как проверить
Посмотрите значение параметра.
systemctl show myapp.socket -p Accept
Как исправить
Для служб, которые сами обслуживают много соединений, поставьте Accept=no. Режим по соединению подходит только простым обработчикам.
4. Служба ищет дескриптор по имени, а имя не задано
Почему происходит
Программы, работающие с несколькими сокетами, различают их по именам из FileDescriptorName=. Без имени они не находят нужный.
Как проверить
Посмотрите имена дескрипторов у сокета.
systemctl show myapp.socket -p FileDescriptorName
Как исправить
Задайте FileDescriptorName= в [Socket] так, как ожидает программа.

Пример вывода

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

● myapp.socket - Socket for myapp
     Active: active (listening) since Mon 2026-09-15 12:00:02 MSK; 5min ago
     Listen: 127.0.0.1:8080 (Stream)

× myapp.service - My application
     Active: failed (Result: exit-code)
myapp[6100]: fatal: listen tcp 127.0.0.1:8080: bind: address already in use

Связанные ошибки

Где встречается чаще всего

Источники

  • systemd.socket(5)
    Accept=, Service=, FileDescriptorName= и передача дескрипторов.
    официальная документация, systemd 255
    сверено 15 сентября 2026
  • sd_listen_fds(3)
    Как программа получает переданные сокеты.
    официальная документация, systemd 255
    сверено 15 сентября 2026
  • Воспроизведено на тестовой машине, systemd 255 (Ubuntu 24.04)
    Воспроизведено связкой сокета и службы, открывающей порт самостоятельно.
    собственная проверка, systemd 255
    сверено 15 сентября 2026