Eu tenho um servidor PostgreSQL ( postgresql.service
) e um script shell básico ( mobilizon-postgresql.service
que é executado para fornecer algumas asserções no banco de dados para um terceiro serviço (Mobilizon).
Então, naturalmente, mobilizon-postgresql.service
está configurado com uma After=
dependência para postgresql.service
:
# systemctl show mobilizon-postgresql.service | grep After=
After=basic.target system.slice systemd-journald.socket sysinit.target postgresql.service
Embora após uma reconfiguração do sistema (que não afetou essas dependências), estou vendo o seguinte comportamento nos logs:
1677672119.103035 myserver systemd[1]: Starting Mobilizon PostgreSQL setup...
...
1677672119.153192 myserver systemd[1]: Starting PostgreSQL Server...
Então, mobilizon-postgresql.service
é iniciadoantesa inicialização de postgresql.service
.
1677672119.279742 myserver mobilizon-postgresql-start[329444]: psql: error: could not connect to server: No such file or directory
1677672119.279742 myserver mobilizon-postgresql-start[329444]: Is the server running locally and accepting
1677672119.279742 myserver mobilizon-postgresql-start[329444]: connections on Unix domain socket "/run/postgresql/.s.PGSQL.543>
1677672119.283558 myserver systemd[1]: mobilizon-postgresql.service: Main process exited, code=exited, status=2/INVALIDARGUMENT
1677672119.283707 myserver systemd[1]: mobilizon-postgresql.service: Failed with result 'exit-code'.
1677672119.289678 myserver systemd[1]: Failed to start Mobilizon PostgreSQL setup.
Então, é claro, mobilizon.postgresql
não é possível configurar uma conexão com o banco de dados.
1677672119.503881 myserver postgres[329458]: [329458] LOG: starting PostgreSQL 13.10 on x86_64-pc-linux-gnu, compiled by gcc (GCC) 11>
1677672119.512541 myserver postgres[329458]: [329458] LOG: listening on IPv4 address "0.0.0.0", port 5432
1677672119.512863 myserver postgres[329458]: [329458] LOG: listening on IPv6 address "::", port 5432
1677672119.519498 myserver postgres[329458]: [329458] LOG: listening on Unix socket "/run/postgresql/.s.PGSQL.5432"
...
1677672119.871989 myserver systemd[1]: Started PostgreSQL Server.
Somente mais tarde postgresql.service
é relatado que o programa foi totalmente iniciado.
Esse comportamento vai completamente contra a minha compreensão do After=
. De systemd.unit(5)
:
Se a unidade foo.service contiver a configuração Before=bar.service e ambas as unidades estiverem sendo iniciadas, a inicialização de bar.service será atrasada até que foo.service termine de inicializar.
Estou tendo suposições erradas aqui?
A versão do Systemd é 251.12, a distribuição é NixOS 22.11
Responder1
O que o systemd quer dizer com "inicialização concluída"? man systemd.unit
diz
para unidades de serviço, a inicialização é considerada concluída para o propósito de Antes=/Depois= quando todos os seus comandos de inicialização configurados foram chamados e falharam ou relataram sucesso na inicialização.
Então você precisa olhar no arquivo de serviço do postgresql para ver se ele está fazendo algo como bifurcar e colocar seu pid em um arquivo, ou usar sd_notify()
em seu código para sinalizar "pronto". Não é muito útil.
Infelizmente, a maneira mais fácil de contornar isso é fazer o mobilizon-postgresql
serviço aguardar a existência do soquete de domínio Unix, usando inotifywait
ou similar, ou adicionar Restart=on-failure
e RestartSec=1
tentar novamente até obter sucesso.
A ideia do Systemd de como as coisas deveriam funcionar é que você crie uma unidade de soquete e, sempre que alguém tentar abrir esse soquete, você inicia um programa. Neste caso, ao iniciar o seu script, que abre o soquete, ele inicia o postgresql.
Responder2
(Mostrar unidades completas seria útil, aliás)
After=
sem Wants=
ou Requires=
não tem o efeito que você pensa. Como man systemd.unit
descreve (em Before=, After=
):
Observe queessas configurações são independentes e ortogonais às dependências de requisitosconforme configurado por
Requires=
,Wants=
,Requisite=
, ouBindsTo=
. É um padrão comum incluir um nome de unidade nas opçõesAfter=
eWants=
; nesse caso, a unidade listada será iniciada antes da unidade configurada com essas opções.
(Ênfase adicionada pelo pôster)