systemctl espera pelo início

2

Eu tenho um script que instala e configura o servidor de tráfego :

yum install -y trafficserver
systemctl start trafficserver

traffic_line -s proxy.config.url_remap.remap_required -v 0
traffic_line -s proxy.config.reverse_proxy.enabled -v 0

O problema é que traffic_line falha com:

[connect] ERROR (main_socket_fd 3): No such file or directory error: could not connect to management port, make sure traffic_manager is running

Isso ocorre porque systemctl start retorna imediatamente, sem esperar que o servidor de tráfego seja realmente iniciado.

Existe uma maneira de dizer que systemctl start só retorna quando o serviço é iniciado?

Se isso não for possível, existe um comando que eu possa executar após systemctl start para realmente esperar que o serviço seja iniciado?

    
por Benjamin 05.12.2017 / 13:35

4 respostas

1

Eu finalmente consegui que funcionasse, depois de várias tentativas.

Primeira tentativa

Depois de procurar na ajuda do systemctl, encontrei o comando is-active :

$ systemctl is-active trafficserver
active

Por isso, escrevi um script de shell para aguardar até que o serviço se torne ativo:

while true; do
    if [ $(systemctl is-active trafficserver) == "active" ]; then
        break
    fi

    sleep 1
done

Infelizmente, mesmo que esse script funcione como esperado ao testá-lo com start / stop, eu ainda estava recebendo o mesmo erro ao executar os comandos traffic_line logo após. Eu acho que o serviço é relatado como ativo antes dos processos reais terem sido totalmente iniciados (provavelmente uma questão de milissegundos).

Segunda tentativa

Então eu tentei de outra maneira. Sabendo que este é o primeiro início do serviço, posso esperar até que o arquivo PID do gerenciador do trafficserver exista. Aqui está o que eu tentei:

while [ ! -f /run/trafficserver/manager.lock ]; do
  sleep 1
done

O mesmo problema: quando o arquivo PID do gerente do trafficserver é gravado, o gerente não está pronto para receber pedidos ainda, então ainda estou recebendo o erro .

Porra, eu não quero usar um cego sleep .

Terceira tentativa

Então acabei verificando se o comando traffic_line em si não falha:

while ! traffic_line --status &> /dev/null; do
    sleep 1
done

E isso funciona!

Bom, mas ...

Infelizmente, a resposta é muito específica para o serviço que estou usando (trafficserver) e não se aplica diretamente a outros serviços.

Se você souber uma resposta mais genérica para essa pergunta, sinta-se à vontade para compartilhá-la.

    
por 05.12.2017 / 16:18
4

This is because systemctl start returns immediately, without waiting for traffic server to be actually started.

Is there a way to tell systemctl start to only return once the service is started?

systemctl start faz esperar que o serviço esteja pronto (exceto se invocado com --no-block ), o serviço precisa indicar isso corretamente (ou seja, não usar Type=simple ). Se o serviço não informar ao sistema quando estiver pronto, nenhuma variação de systemctl is-active , systemctl show , etc. ajudará você.

A solução mais elegante, como mencionado nos comentários, seria uma unidade de soquete. systemd inicia o soquete, traffic_line se conecta a ele, systemd inicia o serviço e traffic_line bloqueia até que o serviço comece a aceitar conexões no descritor de arquivo herdado do systemd.

Como alternativa, você pode usar Type=forking (os garfos de serviço e o PID principal sai assim que o serviço bifurcado estiver pronto) ou Type=notify (o serviço chama sd_notify(0, "READY=1") quando estiver pronto).

Infelizmente, todas essas soluções exigem algum suporte de trafficserver - use o soquete do systemd em vez de alocar seu próprio fork, e espere apropriadamente no processo principal, ou chame sd_notify . O systemd não pode adivinhar magicamente quando o servidor está pronto se o servidor não cooperar:)

Depois de analisar um pouco o código-fonte de trafficserver , parece que ele realmente suporta Type=forking - o servidor é gerado por um comando traffic_cop dedicado, que parece esperar até que o servidor esteja ativo e execute alguns testes básicos (pelo menos o código parece). Então, se você alterar o tipo de serviço, pode funcionar:

# /etc/systemd/system/trafficserver.service.d/type-forking.conf
[Service]
Type=forking
    
por 31.05.2018 / 17:39
1

Sou ruim em scripts de shells, mas acho que você gostaria de testar os dois, o ActiveState e a propriedade SubState se o retorno ativo e executando respectivamente.

$ systemctl show trafficserver -p SubState,ActiveState
ActiveState=active
SubState=running

Depois disso, você poderá executar a segunda parte do seu script.

    
por 06.12.2017 / 12:03
0

A maneira mais simples seria adicionar um sono ao script:

sleep 30

Ou você poderia fazer algum controle de trabalho como aqui

    
por 05.12.2017 / 13:49