Como ter serviço que garante que o programa continue rodando?

2

Eu fiz um serviço chamado thin_keep_alive_service in /etc/init.d . Eu dei chmod +x direitos. O script é o seguinte:

#!/bin/bash

### BEGIN INIT INFO
# Provides:          thin_keep_alive_service
# Required-Start:    $local_fs $network
# Required-Stop:     $local_fs
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description  Keeps Thin servers running
# Description:       This service checks every 30 seconds if at least 
#                    two light weight thin web servers are alive and 
#                    restarts them all from the bundle if not.
###END INIT INFO

while true
do
    # Store an array of the pids of thin
    thin_pid_arr=($(pgrep -f thin))

    # When there are less than two Thin servers left we reboot them all
    if [ ${#thin_pid_arr[@]} -lt 2 ]; then
        cd /root_to_app && bundle exec thin -C /etc/thin/app.yml restart
    fi

    #Wait 30 seconds before checking again
    sleep 30
done

Funciona quando eu o executo como service thin_keep_alive_service start . Mas ele não é executado em segundo plano continuamente após a inicialização, já que meus dois servidores morrem depois de um tempo e nenhum novo é reiniciado.

Como se certificar de que é executado em segundo plano?

    
por Erwin Rooijakkers 07.09.2014 / 23:16

4 respostas

2

Você pode instalar o Thin como um script de nível de execução (sob /etc/init.d/thin) que iniciará todos os seus servidores após a inicialização.

sudo thin install

e configure um arquivo de configuração para cada aplicativo que você deseja iniciar:

thin config -C /etc/thin/myapp.yml -c /var/...

Execute thin -h para obter todas as opções.

Leia a documentação fina !

    
por 08.09.2014 / 00:05
3

Duas coisas:

  1. Os scripts de inicialização devem suportar pelo menos um comando de início e um de parada, e devem sair; ter um loop infinito em um código de inicialização normalmente faz com que o processo de inicialização seja interrompido quando ele chama seu script.

  2. Eu não sei o que o bundle exec thin restart deve fazer, mas, caso contrário, seu script está bem, é provável que o problema esteja lá, ou seja, esse bit não faz o que você pensa. Você pode colocar set -x em seu script para garantir que ele execute o comando quando for necessário.

Dito isto, se você quiser que os serviços sejam reiniciados automaticamente, é quase certamente muito mais limpo usar um supervisor de processos como o runit .

você pode remover um fork () usando while sleep 30 em vez de while true; do ... sleep 30; done . :)

    
por 07.09.2014 / 23:37
1

Como mencionado, você nunca deve ter um loop que bloqueia um script de inicialização.

O que eu faria é criar outro script que seja visto como o serviço. Esse script teria o loop e ele iniciaria o serviço em primeiro plano para que o loop se tornasse algo realmente simples:

#!/bin/sh
while true
do
    start-service ...
    sleep 30
done

No seu arquivo init, você faz referência a esse script com thin ou qualquer outro mecanismo que inicie um serviço. Então você acabou de adicionar uma camada que garante que o serviço continue em execução.

Agora, você também pode querer ter uma maneira de saber quando o usuário tenta parar o servidor ... você não tem isso em seu loop também. Algo assim provavelmente:

#!/bin/sh
while true
do
    start-service ...

    # service properly terminated?
    if ! test -f /var/run/service-id
    then
        exit 0
    fi

    sleep 30
done

Se o arquivo / var / run / service-id for excluído antes que o software "start-service" retorne, você estará bem. Isso também significa que, se o serviço falhar, o arquivo não deve ser excluído automaticamente (obviamente).

Talvez você também possa usar o valor de retorno do serviço. Nesse caso, você poderia fazer isso em vez disso (lembre-se que funciona somente se o próprio serviço bloquear):

#!/bin/sh
while true
do
    if start-service ...
    then
        # service cleanly terminated
        exit 0
    fi

    sleep 30
done

Observe que esse tipo de coisa reiniciará o aplicativo automaticamente, mas não fará nada para forçar o aplicativo. para sair. Se o aplicativo. não falha, mas ainda fica ruim depois de um tempo (por exemplo, lento), então você precisaria de mais heurística para parar ...

    
por 08.09.2014 / 01:43
1

Existem outras maneiras de fazer isso. Nas distribuições Linux mais comuns, você pode usar upstart para verificar se um processo está em execução e fazer algo se não estiver. Outra boa opção, que estou usando atualmente, é systemd .

Mas, se você quiser usar software de terceiros, dê uma olhada em monit e godrb.

    
por 08.09.2014 / 02:26