Address already in use при запуске службы
Сообщение Address already in use значит, что служба пыталась занять адрес, который уже занят. Это одна из самых частых причин, по которым служба не поднимается после перезапуска или правки настроек. Разбор простой: найти владельца порта — и дальше по обстоятельствам.
Что это значит
Формулировки различаются у разных программ: bind() to 0.0.0.0:80 failed (98: Address already in use) у nginx, could not bind IPv4 address у postgresql, Failed to bind у самодельных служб. Это одна и та же ошибка ядра с номером 98 (EADDRINUSE), поэтому разбирается она одинаково.
Отдельный случай — состояние TIME_WAIT после остановки: адрес остаётся занятым десятки секунд. Тогда помогает либо ожидание, либо параметр программы, разрешающий повторное использование адреса.
Вероятные причины
По порядку: сверху то, что встречается чаще.
-
Прежний экземпляр той же службы ещё работает
Самая частая причина. Процесс не завершился при остановке, отвязался от systemd или был запущен вручную в обход службы.
-
Порт занят другой программой
Два веб-сервера на 80-м порту, старый apache при установке nginx, отладочный процесс разработчика. Программы разные, порт один.
-
Служба указана в настройках дважды
Один и тот же адрес прослушивания попал в два файла настроек: основной и включённый из каталога. Программа пытается занять адрес второй раз и получает отказ от себя же.
-
Адрес занят сокетом systemd
При сокет-активации адрес держит
.socket, а не сама служба. Если служба вдобавок пытается занять тот же адрес сама, возникает конфликт с собственным сокетом. -
Адрес в состоянии TIME_WAIT после остановки
После закрытия соединений адрес остаётся занятым до минуты. Немедленный перезапуск службы упирается в это состояние.
Диагностика
Команды идут в том порядке, в котором их стоит выполнять: каждая следующая проверяет то, что осталось после предыдущей.
Главная команда: показывает процесс, который держит адрес, вместе с его PID.
sudo ss -tlnp | grep :ПОРТЗавершает всё, что слушает порт. Применять осознанно: команда не спрашивает подтверждения.
sudo fuser -k -n tcp 8080Точная формулировка от программы: в ней виден адрес и порт, которые не удалось занять.
journalctl -u myapp.service -n 30 --no-pager | grep -i -E "bind|address|in use"Сокеты systemd: если адрес держит один из них, обычный ss покажет процесс systemd, а не вашу службу.
systemctl list-sockets --no-pagerРешение
Решение своё для каждой причины. Сначала определите, какая из них ваша, — иначе правки наложатся друг на друга.
- Почему происходит
- Самая частая причина. Процесс не завершился при остановке, отвязался от systemd или был запущен вручную в обход службы.
- Как проверить
-
Найдите, кто держит порт.
sudo ss -tlnp | grep :8080 sudo systemctl status myapp.service | head -12
- Как исправить
-
Остановите службу штатно и убедитесь, что процессов не осталось. Если процесс не принадлежит службе, завершите его и разберитесь, кто его запустил.
sudo systemctl stop myapp.service sudo ss -tlnp | grep :8080
- Почему происходит
- Два веб-сервера на 80-м порту, старый apache при установке nginx, отладочный процесс разработчика. Программы разные, порт один.
- Как проверить
-
Посмотрите имя процесса-владельца.
sudo ss -tlnp | grep -E ":(80|443)\s" sudo lsof -i :80 2>/dev/null | head
- Как исправить
-
Выберите, какая служба должна занимать порт, и отключите вторую целиком, чтобы она не вернулась после перезагрузки.
sudo systemctl disable --now apache2.service
- Почему происходит
- Один и тот же адрес прослушивания попал в два файла настроек: основной и включённый из каталога. Программа пытается занять адрес второй раз и получает отказ от себя же.
- Как проверить
-
Поищите все объявления адреса в настройках.
sudo grep -rn "listen" /etc/nginx/ 2>/dev/null | grep -v "#" | head -20
- Как исправить
-
Уберите повторное объявление. У nginx на этот случай есть встроенная проверка:
nginx -tукажет файл и строку.
- Почему происходит
- При сокет-активации адрес держит
.socket, а не сама служба. Если служба вдобавок пытается занять тот же адрес сама, возникает конфликт с собственным сокетом.
- Как проверить
-
Посмотрите активные сокеты systemd.
systemctl list-sockets --no-pager | grep 8080 systemctl status myapp.socket
- Как исправить
- Выберите один способ: либо сокет-активация (служба получает готовый дескриптор), либо самостоятельная привязка. Одновременно они не работают.
- Почему происходит
- После закрытия соединений адрес остаётся занятым до минуты. Немедленный перезапуск службы упирается в это состояние.
- Как проверить
-
Посмотрите соединения в состоянии ожидания на нужном порту.
ss -tan | grep -E "TIME-WAIT|8080" | head
- Как исправить
-
Подождите или включите в программе повторное использование адреса (у большинства серверов это уже сделано по умолчанию). В unit-файле помогает
RestartSec=5— пауза перед повторным запуском.
Пример вывода
nginx не может занять 80-й порт: его держит другой веб-сервер. Пример показательный: он собран на тестовой машине специально для этой страницы, а не взят из чужого журнала.
× nginx.service - A high performance web server and a reverse proxy server
Active: failed (Result: exit-code) since Mon 2026-09-15 11:02:10 MSK; 12s ago
Process: 9021 ExecStartPre=/usr/sbin/nginx -t -q -g daemon on; master_process on; (code=exited, status=1/FAILURE)
nginx[9021]: nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)
nginx[9021]: nginx: configuration file /etc/nginx/nginx.conf test failed
systemd[1]: nginx.service: Control process exited, code=exited, status=1/FAILURE
systemd[1]: Failed to start nginx.service - A high performance web server and a reverse proxy server.
Частые вопросы
ss ничего не показывает, а порт занят. Как так?
Скорее всего вы смотрите без sudo: имя процесса видно только с правами root. Ещё вариант — адрес занят в другом сетевом пространстве имён, например внутри контейнера.
Можно ли разрешить двум процессам слушать один порт?
Да, если оба открывают сокет с параметром повторного использования порта (SO_REUSEPORT) — так работает балансировка между рабочими процессами. Но случайное совпадение двух разных служб на одном порту так не лечится.
Связанные ошибки
- bind: Permission denied при привязке к порту Отказ при привязке к порту: обычно порт ниже 1024 у службы от непривилегированного пользователя. Как дать возможность CAP_NET_BIND_SERVICE.
- Cannot assign requested address при привязке Ошибка 99 при привязке: адрес не принадлежит машине или ещё не поднят. Разбор с network-online.target и ip_nonlocal_bind.
- status=1/FAILURE в systemd Код 1/FAILURE означает, что программа запустилась и сама завершилась с ошибкой. Как найти настоящую причину в журнале службы.
- Сокет без Listen: unit загружен, но ничего не слушает В .socket не задан ни один параметр Listen…= — сокет не принимает соединения. Как объявить адрес прослушивания.
- Connection refused в журнале службы Соединение отклонено: служба не может подключиться к базе, кешу или другому сервису. Порядок запуска, адрес, брандмауэр.
- Exec format error при запуске службы Ошибка формата исполняемого файла: не та архитектура, нет строки #!, повреждённый файл или попытка запустить не программу.
- Job for … failed because a timeout was exceeded Задание на запуск прервано по таймауту. Как отличить медленный старт от заблокированного и правильно настроить TimeoutStartSec.
- PostgreSQL: could not bind IPv4 address Кластер PostgreSQL не занимает порт: адрес занят другим экземпляром или остался файл сокета. Разбор.
Где встречается чаще всего
Источники
-
bind(2): ошибка EADDRINUSE
Номер 98 соответствует EADDRINUSE на Linux. -
systemd.socket(5)
Сокет-активация и параметр ReusePort=. -
Воспроизведено на тестовой машине, systemd 255 (Ubuntu 24.04)
Воспроизведено запуском второго экземпляра службы на занятом порту и при сокет-активации.