SystemdDoctor
postgresql.service база данныхчастое

PostgreSQL в systemd: почему кластер не поднимается

В PostgreSQL под systemd есть особенность, которая путает разбор: postgresql.service в Debian и Ubuntu — это пустая обёртка, а настоящая работа идёт в шаблонном unit вида postgresql@16-main.service. Смотреть журнал нужно именно у него.

О службе

Обёртка существует, чтобы одной командой поднимать все кластеры на машине. Она ничего не запускает сама: Type=oneshot с RemainAfterExit=yes. Поэтому её состояние почти всегда active, даже когда кластер не работает. Настоящее состояние смотрят у экземпляра: systemctl status postgresql@16-main.

Вторая особенность — строгие требования к каталогу данных. PostgreSQL отказывается стартовать, если права на каталог шире 0700 (или 0750 в новых версиях) или владелец не совпадает с пользователем службы. Это защита от случайного доступа, и обходить её не нужно — нужно исправить права.

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

Как устроена

Настоящий unitшаблонный postgresql@ВЕРСИЯ-ИМЯ.service, например postgresql@16-main.service
Обёрткаpostgresql.service — oneshot без процессов, её состояние ничего не говорит о кластере
Каталог данных/var/lib/postgresql/ВЕРСИЯ/ИМЯ, права строго 0700 или 0750
Собственный журнал/var/log/postgresql/postgresql-ВЕРСИЯ-ИМЯ.log — там причина, если в journalctl только код
Порт по умолчанию5432, задаётся в postgresql.conf и в файле кластера

Частые ошибки

32 записи базы отмечены за этой службой.

Коды выхода

  • status=1/FAILURE в systemdКод 1/FAILURE означает, что программа запустилась и сама завершилась с ошибкой. Как найти настоящую причину в журнале службы.
  • status=217/USER в systemdКод 217/USER означает, что systemd не смог определить или сменить пользователя из User=. Разбор причин: пользователя нет, имя недопустимо, конфликт с DynamicUser.
  • status=216/GROUP в systemdКод 216/GROUP: systemd не смог определить или сменить группу из Group= или SupplementaryGroups=. Причины и как проверить.
  • status=238/STATE_DIRECTORY в systemdКод 238/STATE_DIRECTORY: не удалось подготовить постоянный каталог службы в /var/lib из StateDirectory=.
  • status=242/NUMA_POLICY в systemdКод 242/NUMA_POLICY: не удалось применить политику размещения памяти NUMA из NUMAPolicy= и NUMAMask=.

Сообщения журнала

Ресурсы и ограничения

Состояния результата

  • Failed with result 'timeout'Состояние timeout: служба не уложилась в отведённое время при запуске, остановке или перезагрузке настроек.
  • Failed with result 'oom-kill'Состояние oom-kill: процесс службы убит из-за нехватки памяти. Как понять, упёрлись в предел службы или в память машины.
  • Failed with result 'exit-code'Состояние exit-code: служба завершилась с ненулевым кодом. Что это сообщение значит и где искать настоящую причину.
  • Job for … failed because a timeout was exceededЗадание на запуск прервано по таймауту. Как отличить медленный старт от заблокированного и правильно настроить TimeoutStartSec.

Конфигурация unit

Зависимости и порядок

Сигналы

  • signal=BUS (status=7/BUS) в systemdПроцесс службы завершён сигналом BUS: ошибка доступа к памяти, часто из-за усечённого файла в отображении или заполненного диска.
  • signal=KILL (status=9/KILL) в systemdПроцесс службы убит сигналом KILL. Кто мог его послать: OOM-killer, таймаут остановки systemd, администратор.

Ошибки служб

Коды выхода этой службы

Числа в status=N ниже 200 назначает сама программа, 200 и выше — systemd, когда не смог подготовить запуск.

statusЧто означает у этой службыКуда смотреть
1/FAILURE самый частый: ошибка в конфигурации, права на каталог данных, занятый порт. Причина — в собственном журнале кластера. разбор
2 проблема с каталогом данных: не найден или не принадлежит нужному пользователю. разбор
убит сигналом KILL нехватка памяти при больших запросах или тесный MemoryMax. разбор

Диагностика

Состояние настоящего unit кластера, а не обёртки.

systemctl status postgresql@16-main --no-pager -l

Собственный журнал кластера: именно там причина отказа запуска.

sudo tail -50 /var/log/postgresql/postgresql-16-main.log

Состояние кластера с точки зрения самого PostgreSQL, минуя systemd.

sudo -u postgres /usr/lib/postgresql/16/bin/pg_ctl -D /var/lib/postgresql/16/main status

Права и владелец каталога данных: при расхождении кластер не стартует.

sudo ls -ld /var/lib/postgresql/16/main

Список кластеров с версиями, портами и состоянием (в Debian и Ubuntu).

pg_lsclusters

Параметры unit, которые тут важны

  • TimeoutStartSec=восстановление после сбоя занимает минуты — значение по умолчанию бывает мало
  • User=кластер работает от postgres; каталог данных должен принадлежать ему
  • MemoryMax=ограничение памяти для базы задавать осторожно: при упоре процесс убивают
  • OOMScoreAdjust=базе обычно снижают привлекательность для OOM-killer
  • Type=notify в современных пакетах: postmaster сообщает о готовности

Частые вопросы

systemctl status postgresql показывает active, но база не отвечает. Почему?

Потому что это обёртка. Она отработала и осталась в состоянии active (exited). Настоящий кластер — в unit postgresql@ВЕРСИЯ-ИМЯ.service, его состояние и надо смотреть.

Кластер не успевает подняться за таймаут. Что делать?

Увеличить TimeoutStartSec= в переопределении unit экземпляра. Убивать восстановление на середине вредно: следующий запуск начнётся заново и займёт ещё больше времени.

Источники

  • Документация PostgreSQL: запуск сервера документация программы
    сверено 15 сентября 2026
  • systemd.service(5) официальная документация
    сверено 15 сентября 2026
  • Воспроизведено на тестовой машине, systemd 255 (Ubuntu 24.04) собственная проверка
    сверено 15 сентября 2026