postgres postgresql service start stop restart reload status

Serviços do PostgreSQL

Várias ações diferentes são necessárias para a gestão de um sistema de gerenciamento de banco de dados (SGBD) como o PostgreSQL. As mais conhecidas são start e stop, mas mesmo elas têm uma profundidade maior que apenas seus nomes indicam. Nesta parte veremos elas a fundo, assim como suas ações companheiras.

Os comandos para gestão dos serviços do PostgreSQL dependem do sistema operacional e da origem dos pacotes instalados. Os comandos a seguir pressupõem o uso dos repositórios PGDG, como vistos antes.

Quando em dúvida sobre qual comando usar, dê preferência ao sistema de gestão de serviços da sua distribuição (systemd, Upstart, openrc...). Em segunda posição, use os comandos pg_ctl quando estritamente necessário. Os scripts de conveniência da distribuição também podem ser úteis para atividades raras como initdb ou upgrade. Se possível, não envie sinais ao PostgreSQL, pois a chance de erro humano na escolha do sinal, na descoberta dos processos do PostgreSQL e no envio ao postgres (ou postmaster em CentOS antes do PG 16) é significativa. Guarde essa última estratégia apenas para automatizar ferramentas e scripts de administração e de alta disponibilidade que não puderem usar as primeiras opções.

Iniciando o serviço (start)

Uma vez que o diretório de dados tenha sido inicializado, é possível iniciar o serviço do PostgreSQL, que irá aceitar conexões por uma porta TCP (5432 por padrão), tratar as requisições SQL vindas dessa conexão, e persistir as alterações no diretório de dados.

CentOS/RHEL

Iniciando o serviço pelo systemd, como root:

[root@pg-1 ~]# systemctl start postgresql-16

Iniciando o serviço manualmente, como postgres:

[postgres@pg-1 ~]$ /usr/pgsql-16/bin/pg_ctl start -D /var/lib/pgsql/16/data

Debian/Ubuntu

Iniciando o serviço pelo systemd, como root:

root@pg-1:~# systemctl start postgresql@16-main

Iniciando o serviço manualmente, como postgres:

postgres@pg-1:~$ /usr/lib/postgresql/16/bin/pg_ctl start -D /var/lib/postgres/16/main

Iniciando o serviço pelo script de conveniência, como postgres ou root:

postgres@pg-1:~$ pg_ctlcluster 16 main start

Conferindo o serviço (status)

Existem diversas formas de observar o serviço do PostgreSQL que está no ar. Algumas envolvem ferramentas básicas de sistema operacional, como ss e pgrep, enquanto outras dependem dos comandos específicos do PostgreSQL.

Com ss podemos listar portas TCP (-t) que estão sendo ouvidas (listening, -l). Quando o PostgreSQL está ouvindo a sua porta padrão 5432, o número dela será substituído pelo nome do serviço (assim como getent services 5432), como a seguir:

[postgres@pg-1 ~]$ ss -t -l
State     Recv-Q    Send-Q       Local Address:Port             Peer Address:Port
LISTEN    0         128              127.0.0.1:postgresql            0.0.0.0:*
LISTEN    0         128                  [::1]:postgresql               [::]:*

Com pgrep podemos consultar processos com o nome postgres (Debian) ou postmaster (CentOS para versões anteriores ao PG 16), que muito provavelmente são processos do PostgreSQL:

[postgres@pg-1 ~]$ pgrep -a postgres
16002 /usr/pgsql-16/bin/postmaster -D /var/lib/pgsql/16/data/
16004 postgres: logger
16006 postgres: checkpointer
16007 postgres: background writer
16008 postgres: walwriter
16009 postgres: autovacuum launcher
16010 postgres: logical replication launcher

Mas as formas com resultado mais confiável são consultando o próprio serviço que foi iniciado recentemente. Isso não só traz o serviço, como também todos os processos abaixo dele, os diretórios de dados e de binários e contabilizações de recursos (CPU, memória, IO, rede/IP) consumidos:

[postgres@pg-1 ~]$ systemctl status postgresql-16
● postgresql-16.service - PostgreSQL 16 database server
   Loaded: loaded (/usr/lib/systemd/system/postgresql-16.service; disabled; vendor preset: disabled)
  Drop-In: /etc/systemd/system/postgresql-16.service.d
           └─override.conf
   Active: active (running) since Mon 2024-09-24 17:13:30 UTC; 9s ago
     Docs: https://www.postgresql.org/docs/16/static/
  Process: 15996 ExecStartPre=/usr/pgsql-16/bin/postgresql-16-check-db-dir ${PGDATA} (code=exited, status=0/SUCCESS)
 Main PID: 16002 (postmaster)
       IP: 12.8K in, 12.8K out
       IO: 9.2M read, 256.0K written
    Tasks: 8 (limit: 2881)
   Memory: 26.7M
      CPU: 46ms
   CGroup: /system.slice/postgresql-16.service
           ├─16002 /usr/pgsql-16/bin/postgres -D /var/lib/pgsql/64/data/
           ├─16004 postgres: logger
           ├─16006 postgres: checkpointer
           ├─16007 postgres: background writer
           ├─16008 postgres: walwriter
           ├─16009 postgres: autovacuum launcher
           └─16010 postgres: logical replication launcher

CentOS/RHEL

Conferindo o serviço pelo systemd, como postgres ou root:

[postgres@pg-1 ~]$ systemctl status postgresql-16

Conferindo o serviço manualmente, como postgres:

[postgres@pg-1 ~]$ /usr/pgsql-16/bin/pg_ctl status -D /var/lib/pgsql/16/data

Debian/Ubuntu

Conferindo o serviço pelo systemd, como postgres ou root:

postgres@pg-1:~$ systemctl status postgresql@16-main

Conferindo o serviço manualmente, como postgres:

postgres@pg-1:~$ /usr/lib/postgresql/16/bin/pg_ctl status -D /var/lib/postgres/16/main

Conferindo o serviço pelo script de conveniência, como postgres ou root:

postgres@pg-1:~$ pg_ctlcluster 16 main status

Ou:

postgres@pg-1:~$ pg_lsclusters

Relendo os arquivos de configuração (reload)

Quando uma configuração é alterada, ela não é aplicada imediatamente. Isso é intencional e desejado, assim o administrador do sistema tem a oportunidade de fazer diversas mudanças nos arquivos de configurações e aplicá-las todas ao mesmo tempo, de forma atômica.

Essa ação de recarregar o conteúdo dos arquivos de configuração é chamada de reload e não interrompe a disponibilidade do serviço, ou seja, não aborta transações em andamento ou impede novas conexões (diferentemente do restart, a seguir).

Uma forma de acionar a ação é enviando o sinal SIGHUP para o processo principal do PostgreSQL. Por exemplo, usando o pid reportado anteriormente como Main PID pelo systemctl status postgresql-16:

[postgres@pg-1 ~]$ kill -HUP 16002

Outra forma é através da chamada da função pg_reload_conf() por uma conexão administrativa ao PostgreSQL:

(psql)# SELECT pg_reload_conf();
 pg_reload_conf
----------------
 t
(1 row)

E as formas restantes são similares às que vimos antes:

CentOS/RHEL

Relendo os arquivos de configuração pelo systemd, como root:

[root@pg-1 ~]# systemctl reload postgresql-16

Relendo os arquivos de configuração manualmente, como postgres:

[postgres@pg-1 ~]$ /usr/pgsql-16/bin/pg_ctl reload -D /var/lib/pgsql/16/data

Debian/Ubuntu

Relendo os arquivos de configuração pelo systemd, como root:

root@pg-1:~# systemctl reload postgresql@16-main

Relendo os arquivos de configuração manualmente, como postgres:

postgres@pg-1:~$ /usr/lib/postgresql/16/bin/pg_ctl reload -D /var/lib/postgres/16/main

Relendo os arquivos de configuração pelo script de conveniência, como postgres ou root:

postgres@pg-1:~$ pg_ctlcluster 16 main reload

Parando o serviço (stop)

Quando um sistema de gerenciamento de banco de dados está em execução, ele gerencia conexões, que podem ter transações ou backups em andamento, assim como gerencia buffers de escrita em disco (guardados na região de memória compartilhada delimitada pelo parâmetro shared_buffers). Então devemos decidir, no momento em que o SGBD for parado, o que fazer com as transações em andamento e com os buffers sujos. Essa decisão influencia diretamente os tempos de parada e de início posterior.

O PostgreSQL tem três modos de parada, cada um com tratamentos diferentes sobre transações e buffers:

modo transações buffers tempos sinal
smart aguarda o término normal das transações escreve os buffers e deixa a instância em estado consistente stop lento e start rápido SIGTERM
fast (padrão) aborta transações em andamento escreve os buffers e deixa a instância em estado consistente stop médio e start rápido SIGINT
immediate aborta transações em andamento descarta buffers sujos e deixa a instância em estado inconsistente stop rápido e start lento SIGQUIT

Como visto acima, cada modo pode ser acionado pelo uso de um sinal diferente enviado ao processo postgres (ou postmaster em CentOS antes do PG 16), similar ao método mostrado no reload.

ATENÇÃO: Nunca tente finalizar o PostgreSQL com um SIGKILL. Esse sinal não permite que o PostgreSQL libere segmentos de memória compartilhada ou semáforos, além de possivelmente deixar os subprocessos do PostgreSQL no ar.

Mais informações sobre como parar o serviço na documentação oficial.

CentOS/RHEL

Parando pelo systemd com modo padrão (fast), como root:

[root@pg-1 ~]# systemctl stop postgresql-16

Parando manualmente com os três modos, como postgres:

[postgres@pg-1 ~]$ /usr/pgsql-16/bin/pg_ctl stop -m smart -D /var/lib/pgsql/16/data
[postgres@pg-1 ~]$ /usr/pgsql-16/bin/pg_ctl stop -m fast -D /var/lib/pgsql/16/data
[postgres@pg-1 ~]$ /usr/pgsql-16/bin/pg_ctl stop -m immediate -D /var/lib/pgsql/16/data

Debian/Ubuntu

Parando pelo systemd com modo padrão (fast), como root:

root@pg-1:~# systemctl stop postgresql@16-main

Parando manualmente com os três modos, como postgres:

postgres@pg-1:~$ /usr/lib/postgresql/16/bin/pg_ctl stop -m smart -D /var/lib/postgres/16/main
postgres@pg-1:~$ /usr/lib/postgresql/16/bin/pg_ctl stop -m fast -D /var/lib/postgres/16/main
postgres@pg-1:~$ /usr/lib/postgresql/16/bin/pg_ctl stop -m immediate -D /var/lib/postgres/16/main

Parando pelo script de conveniência, pelos três modos, como postgres ou root:

postgres@pg-1:~$ pg_ctlcluster 16 main -m smart stop
postgres@pg-1:~$ pg_ctlcluster 16 main -m fast stop
postgres@pg-1:~$ pg_ctlcluster 16 main -m immediate stop

Reiniciando o serviço (restart)

Em alguns casos é necessário reiniciar completamente o serviço, como para aplicar atualizações de versões minoritárias ou aplicar configurações de contexto postmaster. Essa ação faz com que o banco de dados fique indisponível por algum tempo, normalmente de segundos a minutos, dependente do volume de dados, volume de transações, do hardware e de alguns fatores externos. Portanto, é comum evitarmos ela nos casos em que um reload seria suficiente. Em outros casos, montamos um cluster de alta disponibilidade para que o serviço seja chaveado para outro nó antes do reinício.

O reinício pode ser alcançado simplesmente executando as ações de stop seguida do start. Contudo, também existe a ação restart, que engloba as duas ações anteriores em uma, e que pode ser invocada como as anteriores:

CentOS/RHEL

Reiniciando pelo systemd, como root:

[root@pg-1 ~]# systemctl restart postgresql-16

Reiniciando manualmente, como postgres:

[postgres@pg-1 ~]$ /usr/pgsql-16/bin/pg_ctl restart -D /var/lib/pgsql/16/data

Debian/Ubuntu

Reiniciando pelo systemd, como root:

root@pg-1:~# systemctl restart postgresql@16-main

Reiniciando manualmente, como postgres:

postgres@pg-1:~$ /usr/lib/postgresql/16/bin/pg_ctl restart -D /var/lib/postgres/16/main

Reiniciando pelo script de conveniência, como postgres ou root:

postgres@pg-1:~$ pg_ctlcluster 16 main restart

Habilitando o serviço para iniciar no boot

Cada sistema operacional tem o seu próprio mecanismo de gestão de serviços. Mas no systemd os comandos são:

CentOS/RHEL

Habilitando no systemd, como root:

[root@pg-1 ~]# systemctl enable postgresql-16

Debian/Ubuntu

Habilitando no systemd, como root:

root@pg-1:~# systemctl enable postgresql@16-main

Permitindo que o usuário postgres possa controlar o serviço

Existem várias formas de permitir que um usuário comum controle um serviço.

Polkit

Serviços gerenciados pelo systemd podem ser submetidos a um conjunto de regras implementadas pelo Polkit (antigo Policy Kit). Essas regras são escritas em arquivos em /etc/polkit-1/rules.d e avaliadas na ordem lexicográfica dos nomes dos arquivos. Então podemos criar um arquivo /etc/polkit-1/rules.d/30-postgres.rules com uma regra permitindo que usuários pertencentes ao grupo postgres possam usar todas as ações sobre os serviços com nomes que comecem com postgres, como o seguinte exemplo:

polkit.addRule(function(action, subject) {
    if (action.id == "org.freedesktop.systemd1.manage-units" &&
        /^postgresql.*\.service$/.test(action.lookup("unit")) &&
        subject.isInGroup("postgres"))
    {
        return polkit.Result.YES;
    }
})

Dessa forma, o usuário postgres consegue controlar o serviço diretamente:

[postgres@pg-1 ~]$ systemctl start postgresql-16

Em um único arquivo é possível adicionar diversas regras, como outras permitindo as ações certas entre os serviços do postgres, barman, repmgr e seus usuários.

Sudo

A forma mais popular é com sudo, mas também é a mais criticada por questões de segurança, já que permite não só controle dos serviços, mas execução de comandos gerais, sem a possiblilidade de bloquear comandos de forma confiável. Use com cuidado.

Crie o arquivo /etc/sudoers.d/postgres para permitir o gerenciamento do serviço pelo postgres/repmgr com o conteúdo:

Defaults:postgres !requiretty
postgres ALL = NOPASSWD: \
    /usr/bin/systemctl reload postgresql-16, \
    /usr/bin/systemctl restart postgresql-16, \
    /usr/bin/systemctl start postgresql-16, \
    /usr/bin/systemctl status postgresql-16, \
    /usr/bin/systemctl stop postgresql-16

Dessa forma, o usuário postgres consegue controlar o serviço indiretamente através do sudo:

[postgres@pg-1 ~]$ sudo systemctl start postgresql-16