Como você usa o systemd para garantir que o banco de dados remoto esteja disponível

3

No SysV, posso usar uma condição para garantir que um aplicativo não tente iniciar antes que o banco de dados esteja ativo e em execução. Eu dou ao script de inicialização algum tempo para esperar, e finalmente desisto depois de um período de tempo se o serviço de banco de dados ainda estiver indisponível.

start() {
local exec=/path/to/exec
local tries=1
[ -x $exec ] || exit 5
echo -n $"Starting $prog: "


#check communication to database
if ! [ 2>/dev/null : < /dev/tcp/$dbHost/$dbPort ]
    then
        while ! [ 2>/dev/null : < /dev/tcp/$dbHost/$dbPort ] && [ ! $tries -ge 5 ]
            do
                >&2 echo -e "Could not connect to the database on $dbHost\nWaiting 10 seconds to check database status, attempt $tries"
                sleep 10
                ((tries++))
        done
        sleep 10
        if ! (: < /dev/tcp/$dbHost/$dbPort ) 2>/dev/null
            then
                >&2 echo -e "Could not connect to the database on $dbHost aborting startup of $exec"
                exit 1
        fi
fi

Estou procurando um cenário semelhante na documentação e no google, mas não encontrei nada que não esteja referenciando serviços locais.

    
por Michael Kelly 23.03.2018 / 18:37

2 respostas

1

Você examinou o ExecStartPre na documentação do serviço systemd?

Sugiro colocar seu teste de banco de dados em um script, use exit 0 em sucesso e exit 1 em falha e, em seguida, execute-o com ExecStartPre . Você então iniciaria seu aplicativo usando ExecStart .

    
por 23.03.2018 / 19:53
2

@ A resposta da GracefulRestart é a melhor se você tiver apenas um serviço, dependendo da disponibilidade do banco de dados. No entanto, se você tiver vários serviços que possuem esse requisito, faça um serviço que todos os serviços podem ter uma Requires= de dependência para:

/etc/systemd/system/[email protected]

[Unit]
Description=Checks database availability on %I
After=network.target
Requires=network.target

[Service]
Type=oneshot
RemainAfterExit=true
ExecStart=/path/to/portopen.sh %I

[Install]
WantedBy=default.target

/path/to/portopen.sh

#!/bin/bash
dbhost=${1:-localhost}
dbport=${2:-5678}
maxtries=${3:-5}
wait=${4:-10}
tries=1

# Check communication to database
while ! [ 2>/dev/null : < /dev/tcp/$dbhost/$dbport ]; do
   echo "Unable to connect to database on $dbhost TCP/$dbport (attempt $tries): retrying in $wait seconds" >&2
   (( tries++ ))
   if [[ $tries -le $maxtries ]]; then
      sleep $wait
   else
      echo "Unable to connect to database on $dbhost TCP/$dbport: aborting"
      exit 1
   fi
done

Tornei o script um pouco mais flexível caso você altere ou adicione servidores de banco de dados, ou as alterações de portas, ou queira alterar o número de novas tentativas por nível de serviço. Se você não precisa disso, basta chamar o serviço portopen.service e remover as %I partes.

Digamos que seu servidor de banco de dados esteja em foobar e seu aplicativo de banco de dados seja executado em foobarapp.service . Faça as seguintes alterações em foobarapp.service :

# systemctl edit foobarapp.service

[no editor]

[Unit]
[email protected]
[email protected]

Em seguida, recarregue systemd e inicie e ative a verificação:

# systemctl daemon-reload
# systemctl enable [email protected]

Você pode então reiniciar foobarapp.service quando quiser. Ele só deve começar se [email protected] retornar com sucesso.

Se ainda não existir, o serviço de aplicativo de banco de dados foobarapp.service ficaria assim:

/etc/systemd/system/foobarapp.service

[Unit]
Description=Foobar database application
# Add any other dependencies here
[email protected]
[email protected]

[Service]
# If it is a daemon, use "forking" instead
Type=simple
ExecStart=/path/to/exec

[Install]
WantedBy=default.target
    
por 23.03.2018 / 20:37