systemd ignora o código de retorno ao iniciar o serviço

5

Eu corri para esse problema enquanto escrevia o arquivo unitário para um daemon simples. Quando o daemon retorna '1' no sistema de inicialização, ele simplesmente o ignora, e parece que o daemon foi iniciado com sucesso enquanto está realmente morto.

Por exemplo, eu tenho um shell script muito simples:

#!/bin/bash
exit 1

Assim, o arquivo unitário é assim:

[Unit]
Description=test service
After=syslog.target

[Service]
User=testuser
Group=testuser
ExecStart=/usr/local/bin/return1

[Install]
WantedBy=multi-user.target

Tentando começar, parece ok:

# service testservice start
# echo $?
0

Mas na verdade está morto:

# service testservice status
● testservice.service - test service
   Loaded: loaded (/etc/systemd/system/testservice.service; enabled)
   Active: failed (Result: exit-code) since Fri 2016-01-22 14:51:45 MSK; 1min 13s ago
  Process: 16416 ExecStart=/usr/local/bin/return1 (code=exited, status=1/FAILURE)
 Main PID: 16416 (code=exited, status=1/FAILURE)

Jan 22 14:51:45 servername systemd[1]: Started test service.
Jan 22 14:51:45 servername systemd[1]: testservice.service: main process exited, code=exited, status=1/FAILURE
Jan 22 14:51:45 servername systemd[1]: Unit testservice.service entered failed state.

Parece que o systemd acha que o daemon foi iniciado com sucesso, mas caiu depois.

Eu tentei resolver esse problema alterando o tipo de serviço para 'forking' e outros - isso funciona bem em um caso de código diferente de zero, mas o serviço é realmente 'simples', então em um caso e mantém o terminal ocupado.

Como eu gerencio esse tipo de serviço? Ou pode ser que seja necessário consertar algo no código daemon?

OS debian 8 x64, systemd 215

    
por Paul K. 22.01.2016 / 13:26

1 resposta

3

Para que systemd detecte se o processo foi iniciado com êxito, você deve usar Type=forking , bifurcar seu processo em um script auxiliar e verificar esse script se o processo foi iniciado com êxito. Com bifurcação, systemd aguardará o término do comando ExecStart e verificará seu status de saída.

Você deve alterar o arquivo da unidade assim:

[Unit]
Description=test service
After=syslog.target

[Service]
Type=forking
User=testuser
Group=testuser
ExecStart=/usr/local/bin/fork_service

[Install]
WantedBy=multi-user.target

e em /usr/local/bin/fork_service você deve ter algo assim:

#!/bin/bash

# Run your process in background
/path/to/your_service &

# Check if the services started successfully 
if ! kill -0 $! 2>/dev/null; then
    # Return 1 so that systemd knows the service failed to start
    exit 1
fi

Estou aqui apenas verificando se o PID do processo em segundo plano ainda está ativo, mas você pode ter qualquer verificação que desejar. A única coisa importante é que este script sai com 0 se o processo foi iniciado com sucesso, ou um valor positivo diferente de zero se falhou.

Além disso, você não precisa usar o Bash para criar um processo, você pode usar qualquer idioma que quiser.

    
por 17.02.2017 / 17:39