Blog JSystems - uwalniamy wiedzę!

Szukaj

PostgreSQL

PostgreSQL na Red Hat, Rocky lub Alma nie startuje po instalacji - brak initdb

W skrócie

  • Problem: po instalacji postgresql16-server usługa postgresql-16 nie startuje, a dziennik zgłasza, że katalog danych jest pusty albo go brak.
  • Dlaczego: na systemach z rodziny Red Hat pakiet nie inicjalizuje klastra, a skrypt uruchamiany przed startem usługi blokuje start bez plików klastra.
  • Rozwiązanie: zakładamy klaster poleceniem postgresql-16-setup initdb, a dla własnego katalogu najpierw ustawiamy PGDATA w nadpisaniu usługi.

Ten problem dotyczy instalacji PostgreSQL 16 z oficjalnego repozytorium PGDG na Red Hat Enterprise Linux, Rocky Linux i AlmaLinux. Pakiet instaluje się bez błędów, a pierwsze uruchomienie usługi kończy się niepowodzeniem. Pokażemy, co sprawdza usługa przed startem, jak zainicjalizować klaster w katalogu domyślnym albo własnym i jak potwierdzić, że serwer pracuje na właściwym PGDATA.

Jak to wygląda w praktyce

Instalacja przebiega bez błędów:

sudo dnf install -y https://download.postgresql.org/pub/repos/yum/reporpms/EL-9-x86_64/pgdg-redhat-repo-latest.noarch.rpm
sudo dnf install -y postgresql16-server
sudo systemctl start postgresql-16

Adres repozytorium dotyczy wersji 9 systemu. Na wersji 8 albo 10 zmień w nim EL-9 na EL-8 albo EL-10, a na wersji 8 przed instalacją serwera wyłącz wbudowany moduł: sudo dnf -qy module disable postgresql.

Polecenie systemctl start kończy się niepowodzeniem, a systemctl status postgresql-16 pokazuje stan failed. Powód zapisał w dzienniku systemd (sudo journalctl -u postgresql-16 -n 20 --no-pager) skrypt sprawdzający, uruchamiany przed serwerem:

"/var/lib/pgsql/16/data/" is missing or empty.
Use "/usr/pgsql-16/bin/postgresql-16-setup initdb" to initialize the database cluster.
See /usr/share/doc/postgresql16/README.rpm-dist for more information.

Ten sam komunikat zobaczysz w drugim wariancie: klaster założony ręcznie przez initdb w innym katalogu, na przykład /data_pg, a usługa nadal szuka danych w lokalizacji domyślnej.

Dlaczego tak się dzieje

Na Ubuntu instalacja pakietu od razu tworzy i uruchamia klaster. Na systemach z rodziny Red Hat, zgodnie z zasadami tych dystrybucji, PostgreSQL nie jest ani inicjalizowany, ani włączany do autostartu automatycznie. Plik usługi /usr/lib/systemd/system/postgresql-16.service ustawia Environment=PGDATA=/var/lib/pgsql/16/data/ i przed startem serwera wykonuje ExecStartPre=/usr/pgsql-16/bin/postgresql-16-check-db-dir ${PGDATA}.

Ten skrypt sprawdza, czy w PGDATA, czyli katalogu danych klastra, jest plik PG_VERSION i katalog base. Jeśli ich nie ma, wypisuje komunikat z poprzedniej sekcji i kończy się kodem 1, więc systemd nie uruchamia serwera. Autorzy pakietu celowo nie wywołują initdb automatycznie. Komentarz w skrypcie wskazuje ryzyko nadpisania cennej bazy, na przykład na zdalnym wolumenie, który montuje się z opóźnieniem.

Ten sam skrypt zatrzyma start także wtedy, gdy w PGDATA leży klaster z poprzedniej wersji. Wypisuje wtedy An old version of the database format was found. i podpowiada aktualizację klastra zamiast ponownego initdb.

Jak to rozwiązać krok po kroku

  1. Potwierdź przyczynę: sudo ls -la /var/lib/pgsql/16/data/. Pusty albo nieistniejący katalog oznacza, że klaster nie został zainicjalizowany.
  2. Klaster w katalogu domyślnym założysz skryptem z pakietu: sudo /usr/pgsql-16/bin/postgresql-16-setup initdb. Skrypt wypisze Initializing database ... OK, a przebieg initdb zapisze w /var/lib/pgsql/16/initdb.log. Wywołuje initdb z opcjami -A scram-sha-256 --auth-local=peer, więc lokalnie przez gniazdo zalogujesz się jako systemowy użytkownik postgres bez hasła, a połączenia TCP wymagają hasła. Dodatkowe opcje initdb przekażesz zmienną PGSETUP_INITDB_OPTIONS.
  3. Jeśli dane mają leżeć w innym katalogu, nie edytuj pliku usługi w /usr/lib/systemd/system, bo aktualizacja pakietu go nadpisze (ostrzega o tym komentarz w pliku). Utwórz nadpisanie poleceniem sudo systemctl edit postgresql-16 (plik trafi do katalogu /etc/systemd/system/postgresql-16.service.d) i wpisz:
    [Service]
    Environment=PGDATA=/data_pg/
    Ten sam komentarz przypomina, że zmiana PGDATA zwykle wymaga też dostosowania SELinux. Nadaj nowemu katalogowi etykietę katalogu danych PostgreSQL: sudo semanage fcontext -a -t postgresql_db_t "/data_pg(/.*)?", a jeśli katalog już istnieje, także sudo restorecon -R -v /data_pg.
  4. Dla nowego katalogu uruchom sudo /usr/pgsql-16/bin/postgresql-16-setup initdb. Skrypt odczytuje PGDATA z ustawień usługi (systemctl show -p Environment) i sam tworzy brakujący katalog z właścicielem postgres i prawami tylko dla niego, a potem wywołuje dla niego restorecon. Jeśli katalog już istnieje, na przykład jako punkt montowania, skrypt nie zmieni jego właściciela, więc najpierw wykonaj sudo chown postgres:postgres /data_pg i sudo chmod 700 /data_pg. Jeśli klaster już tam jest, bo założyłeś go ręcznie, skrypt odpowie Data directory is not empty! i niczego nie zmieni. Wtedy pomiń ten krok.
  5. Jeśli wcześniej uruchomiłeś ten klaster ręcznie, zatrzymaj go: sudo -u postgres /usr/pgsql-16/bin/pg_ctl -D /data_pg stop. Usługa i proces uruchomiony przez pg_ctl nie wiedzą o sobie, a drugi start na zajętym porcie się nie uda. Potem włącz autostart i uruchom usługę: sudo systemctl enable postgresql-16 oraz sudo systemctl start postgresql-16.

Jak sprawdzić, że zadziałało

Sprawdź trzy rzeczy:

sudo systemctl status postgresql-16
sudo systemctl show -p Environment postgresql-16
sudo -u postgres /usr/pgsql-16/bin/psql -c "SHOW data_directory;"

Usługa powinna być w stanie active (running). Drugie polecenie pokazuje PGDATA, które systemd przekazuje serwerowi, a trzecie katalog, z którego serwer faktycznie pracuje. Obie ścieżki muszą wskazywać ten sam katalog, przy czym SHOW data_directory pokazuje ścieżkę bez końcowego ukośnika. Parametr data_directory ma kontekst postmaster, czyli ustala się go przy starcie serwera, więc wynik odpowiada bieżącemu uruchomieniu. Po restarcie maszyny usługa powinna wstać sama, bo ma włączony autostart.

Powiązane problemy

Wróć do listy: 112 najczęstszych pytań i problemów z PostgreSQL

Najczęściej zadawane pytania

Dlaczego na Red Hat PostgreSQL nie inicjalizuje klastra sam, tak jak na Ubuntu?
Takie są zasady dystrybucji z rodziny Red Hat: instalacja nie zakłada klastra i nie włącza autostartu. Autorzy pakietu PGDG uzasadniają to w komentarzu skryptu sprawdzającego ryzykiem nadpisania cennej bazy, na przykład na zdalnym wolumenie, który montuje się z opóźnieniem.
Gdzie PostgreSQL 16 z repozytorium PGDG trzyma dane na Red Hat?
Domyślnie w /var/lib/pgsql/16/data/, bo taką wartość PGDATA ustawia plik usługi postgresql-16.service. Programy serwera leżą w /usr/pgsql-16/bin/, a log z inicjalizacji klastra trafia do /var/lib/pgsql/16/initdb.log.
Jak zainicjalizować klaster w innym katalogu niż domyślny?
Najpierw ustaw nowe PGDATA w nadpisaniu usługi przez systemctl edit postgresql-16, potem uruchom postgresql-16-setup initdb. Skrypt odczyta ścieżkę z ustawień usługi, sam utworzy katalog z właścicielem postgres i założy w nim klaster. Pamiętaj o konfiguracji SELinux.
Co oznacza komunikat Data directory is not empty?
Skrypt postgresql-16-setup znalazł w PGDATA plik PG_VERSION, czyli klaster już istnieje, i nie inicjalizuje go ponownie, więc istniejące dane zostają nietknięte. Wtedy wystarczy uruchomić usługę, a jeśli klaster założyłeś ręcznie, upewnij się, że usługa wskazuje właśnie ten katalog.
Czy mogę edytować plik /usr/lib/systemd/system/postgresql-16.service?
Nie jest to zalecane, bo aktualizacja pakietu nadpisze ten plik i zmiany przepadną. Komentarz w samym pliku zaleca nadpisanie (drop-in) w katalogu /etc/systemd/system/postgresql-16.service.d, które najprościej utworzysz poleceniem systemctl edit postgresql-16.

Komentarze (0)

Musisz być zalogowany by móc dodać komentarz. Zaloguj się przez Google

Brak komentarzy...