PostgreSQL не запускается: ошибка «could not bind IPv4 socket» - причины и решения
Если после попытки запустить PostgreSQL вы видите ошибку could not bind IPv4 socket: Address already in use - вы не одиноки. Это одна из самых частых проблем при старте сервера. Статья объяснит, почему она возникает, покажет все способы диагностики и пошагово выведет PostgreSQL в рабочее состояние.
Что означает эта ошибка
PostgreSQL при старте пытается занять TCP-порт (по умолчанию 5432) на определённом IP-адресе. Если этот порт уже занят другим процессом, ядро Linux или Windows отказывает - и сервер падает с сообщением:
FATAL: could not bind IPv4 socket: Address already in use
HINT: Is another postmaster already running on port 5432? If not, wait a few seconds and retry.Это не баг PostgreSQL - это штатная защита операционной системы от конфликта сокетов.
Почему возникает проблема
Три основных причины:
Уже запущен другой экземпляр PostgreSQL (возможно, он завис или не завершился корректно).
Порт 5432 занят другим приложением - pgBouncer, устаревшим Docker-контейнером или сторонней программой.
Остался «мёртвый» PID-файл (postmaster.pid) после некорректного завершения, и PostgreSQL думает, что уже запущен.
Частые ошибки пользователей
Удалять postmaster.pid вслепую, не проверив - действительно ли процесс завершён. Это может повредить базу данных, если PostgreSQL ещё работает.
Перезагружать сервер «на удачу» без диагностики - проблема вернётся при следующем запуске, если корень не устранён.
Менять порт в конфигурации, не разобравшись в причине. Это временный костыль, а не решение.
Пошаговое решение
Шаг 1 - Найти, что занимает порт
На Linux / macOS:
# Найти процесс на порту 5432
sudo ss -tlnp | grep 5432
# или
sudo lsof -i :5432На Windows (PowerShell):
netstat -ano | findstr :5432
# Затем по PID
tasklist /FI "PID eq 1234"Шаг 2 - Если порт занят другим PostgreSQL
# Показать все процессы postgres
ps aux | grep postgres
# Корректно остановить через systemd
sudo systemctl stop postgresql
# Если не помогло - принудительно завершить (замените PID)
sudo kill -9 1234Шаг 3 - Если остался мёртвый postmaster.pid
# Найти data directory
sudo -u postgres psql -c "SHOW data_directory;"
# Убедиться, что процесс из PID-файла не существует
cat /var/lib/postgresql/14/main/postmaster.pid
kill -0 <PID_ИЗ_ФАЙЛА> # Если "No such process" - можно удалять
# Только если процесс точно не запущен!
sudo rm /var/lib/postgresql/14/main/postmaster.pidШаг 4 - Если порт занят сторонней программой
Вариант А: завершить чужой процесс, если он не нужен.
Вариант Б: сменить порт PostgreSQL:
# Открыть конфиг
sudo nano /etc/postgresql/14/main/postgresql.conf
# Изменить строку (убрать # и поставить другой порт)
port = 5433
# Перезапустить
sudo systemctl restart postgresqlПосле смены порта не забудьте обновить строки подключения во всех приложениях.
Шаг 5 - Запустить и проверить
sudo systemctl start postgresql
sudo systemctl status postgresql
# Ожидаемый результат:
# ● postgresql.service - PostgreSQL Database Server
# Active: active (running) since ...
Примеры реальных сценариев
Docker-контейнер не остановился
# Найти контейнер с маппингом порта
docker ps | grep 5432
# Остановить
docker stop <container_id>Несколько кластеров PostgreSQL на одном хосте
# Посмотреть все кластеры (Debian/Ubuntu)
pg_lsclusters
# Вывод покажет, какой кластер на каком порту:
# Ver Cluster Port Status
# 14 main 5432 online
# 15 test 5433 downЧасто задаваемые вопросы (FAQ)
Можно ли просто удалить postmaster.pid? Только если вы убедились, что процесс PostgreSQL действительно не запущен. Команда kill -0 <PID> должна вернуть «No such process». Иначе удаление PID-файла при работающем сервере ничего не даст.
Ошибка возникает только после перезагрузки - почему? Скорее всего, PostgreSQL не успевает запуститься раньше другой службы, которая уже занимает порт. Проверьте порядок автозапуска: systemctl list-dependencies postgresql.
Как проверить, что PostgreSQL слушает нужный порт? ss -tlnp | grep postgres или pg_isready -h localhost -p 5432 - вторая команда удобнее, она сразу показывает, отвечает ли сервер.
PostgreSQL запускается, но сразу падает. Где смотреть логи? На Debian/Ubuntu: journalctl -u postgresql --no-pager -n 50 или /var/log/postgresql/postgresql-*.log. На macOS (Homebrew): brew services info postgresql.
Что делать, если порт 5432 занят pgBouncer? Переведите pgBouncer на другой порт (например, 6432), а PostgreSQL оставьте на 5432. pgBouncer должен стоять перед PostgreSQL, а не вместо него на том же порту.
Ошибка только для IPv4, но не IPv6 - это нормально? Да. Если PostgreSQL настроен слушать listen_addresses = '*', он пробует занять и IPv4, и IPv6. Если IPv6 свободен, но IPv4 занят - вы увидите ровно такую ошибку. Решение то же - освободить порт.
Как запретить PostgreSQL слушать IPv4 и работать только через Unix-socket? В postgresql.conf установите listen_addresses = '' (пустая строка). Тогда TCP-порт вообще не будет открываться. Подходит для локальных инсталляций.
Помогает ли перезагрузка сервера? Временно - да. После перезагрузки мёртвые процессы исчезнут. Но если в автозапуске есть конфликтующий сервис, проблема вернётся. Лучше устранить причину.
Полезные советы и лучшие практики
Всегда используйте systemctl stop, а не kill -9 для штатной остановки - это даёт серверу время корректно завершить транзакции.
Для нескольких экземпляров PostgreSQL на одной машине используйте разные порты и разные data-директории - и документируйте это.
В CI/CD и Docker Compose явно прописывайте порты и проверяйте их доступность через pg_isready перед запуском приложения.
Добавьте PostgreSQL в мониторинг (например, Prometheus + postgres_exporter), чтобы узнавать о сбоях до того, как они станут проблемой.
Итог
Ошибка could not bind IPv4 socket почти всегда означает конфликт порта. Алгоритм прост: найти занявший порт процесс (ss -tlnp или lsof), корректно завершить его или перенести на другой порт, проверить наличие мёртвого PID-файла. После этого PostgreSQL запустится без проблем.
Комментарии
Чтобы оставить комментарий, войдите в аккаунт.