dcrd como um serviço do Linux

8 minutos de leitura

1. Introdução

Administradores de sistemas desejam que os serviços disponibilizados sejam executados de forma contínua e que sejam automaticamente iniciados ou reiniciados após uma interrupção para evitar indisponibilidade de serviços e informações.

Serviços do Linux podem ser configurados para reiniciar após a ocorrência de um problema através do gerenciador de serviços, também conhecidos como sistemas de inicialização (init systems). Gerenciadores de serviços iniciam, reiniciam e terminam serviços de acordo com comandos especificados, dependências e runlevels.

As soluções dependem da distribuição do Linux usada e do sistema de gerenciamento padrão que vem com ela, como pode ser conferido na lista a seguir:

  • System V é o antigo sistema de inicialização nas distribuições:
    • Debian 6 e anteriores
    • Ubuntu 9.04 e anteriores
    • CentOS 5 e anteriores
  • Upstart:
    • Ubuntu 9.10 até Ubuntu 14.10
    • CentOS 6
  • systemd é o sistema de inicialização nas distribuições mais recentes, como:
    • Debian 7 e posteriores
    • Ubuntu 15.04 e posteriores
    • CentOS 7

Systemd é um gerenciador de serviços do Linux e o gerenciador padrão do Debian a partir do Debian Jessie. No systemd as tarefas são organizadas em unidades (units), arquivos de configuração individuais. As units mais comuns são serviços (.service), mount points (.mount), dispositivos (.device), sockets (.socket), e timers (.timer). Por exemplo, para iniciar o serviço do SSH a unit ssh.service é utilizada.

O systemd coloca cada serviço em um control group (cgroup) dedicado com o nome do serviço. Kernels modernos suportam isolamento de processos e alocação de recursos com base em cgroups.

Para saber mais sobre o systemd, veja os links no final do artigo.

2. Configuração

Os passos a seguir foram executados em um Debian 9 64-bit.

A instalação automática via dcrinstall documentada no artigo Instalando o dcrd sugere que os executáveis do Decred sejam instalados no diretório /opt, que um link simbólico para /opt/decred seja criado e que um usuário comum chamado dcrduser seja usado para iniciar o dcrd. Essas configurações estão refletidas no arquivo de configuração do serviço do dcrd a seguir. A instalação via dcrinstall também instala o dcrctl na mesma estrutura.

Crie um arquivo chamado dcrd.service e cole nele o seguinte conteúdo:

# dcrd termination depends on dcrctl to send the command via RPC.
#
# dcrd reference doc:
# https://docs.decred.org/advanced/manual-cli-install/
#
[Unit]
Description=The full node blockchain server of Decred network
Documentation=http://decred.org/
After=network.target

[Service]
Type=simple
ExecStart=/opt/decred/dcrd --addrindex
ExecStop=/opt/decred/dcrctl stop
TimeoutStopSec=5
KillMode=mixed
Restart=on-abnormal
User=dcrduser
Group=users

[Install]
WantedBy=multi-user.target

Veja a seguir a explicação de cada diretiva:

Diretivas da seção [Unit]

Description: Descrição do nome e funcionalidade da unit.

Documentation: URL ou man page da documentação do serviço.

After: As units listadas nessa diretiva são iniciadas antes de iniciar essa unit. Isso não implica em uma relação de dependência. Se for necessária uma relação de dependência a diretiva Requires deve ser usada.

Diretivas da seção [Install]

WantedBy: Especifica uma relação de dependência entre units. Por exemplo, se a unit atual tem a diretiva WantedBy=multi-user.target, quando o sistema entrar em modo multiusuário ele carregará a unit atual porque há uma relação de dependência entre o modo multiusuário do Linux e o serviço dcrd.

Diretivas da seção [Service]

Type: “simple”: O processo principal do serviço está especificado no ExecStart. Esse é o padrão caso a diretiva Type não seja usada, mas a diretiva ExecStart sim. As outras opções incluem uso de processos child através de forking e informar o systemd que esse processo terá vida curta e que portanto deve esperar o término para continuar carregando outras units.

ExecStart: Indica o caminho completo e os argumentos do comando que inicia o serviço. Se o caminho for precedido por um “-“, términos com código de saída diferente de zero (falha) serão aceitos sem marcar o término como falha. Indique o caminho da sua instalação do dcrd. A opção --addrindex é necessária para pesquisas de endereços feitas através da interface do dcrdata. Se não pretende usar o dcrdata pode remover a opção.

ExecStop: Indica o caminho completo e os argumentos do comando usado para parar o serviço. Se não houver um comando especificado ou o parâmetro não for incluso no arquivo, o processo será terminado imediatamente quando o serviço for parado. Para terminar o dcrd de forma sutil é necessário usar o dcrctl com o comando stop. Indique o caminho da instalação do seu dcrctl.

Restart: Indica as circunstâncias nas quais o systemd tentará reiniciar o serviço automaticamente. Os valores podem ser “always”, “on-success”, “on-failure”, “on-abnormal”, “on-abort”, ou “on-watchdog”.

Causas de saída e efeito do Restart em cada uma delas:

Causas de saída no always on-success on-failure on-abnormal on-abort on-watchdog
Clean exit code or signal   X X        
Unclean exit code   X   X      
Unclean signal   X   X X X  
Timeout   X   X X    
Watchdog   X   X X   X

TimeoutStopSec: Configura o tempo que o systemd aguardará antes de marcar como falha ou terminar o serviço que não foi parado da forma correta com o comando em ExecStop.

KillMode: Configura como os processos dessa unit devem ser terminados. As opções são “control-group”, “process”, “mixed” e “none”.

  • control-group: todos os processos dentro do control group da unit serão terminados com a parada da unit (para serviços: após o comando stop ser executado, como configurado em ExecStop).
  • process: apenas o processo principal é terminado.
  • mixed: um sinal SIGTERM é enviado ao processo principal enquanto sinais SIGKILL são enviados a todos os processos restantes no control group da unit.
  • none: nenhum processo é terminado. Nesse caso, apenas o comando stop é executado no término da unit, mas nenhum processo será encerrado de outra forma. Processos que ainda estiverem sendo executados continuarão no control group, que continuará existindo até ficar vazio.

User: Com qual usuário do sistema o serviço deve ser executado. Esse parâmetro pode ser ocultado.

Group: Com qual grupo do sistema o serviço deve ser executado. Esse parâmetro pode ser ocultado.

2.1. Habilitação do serviço

Mova o arquivo dcrd.service para a pasta do sistema que contém outros arquivos de configuração de serviços como esse. Esse passo é importante para que o comando seguinte possa localizar o arquivo do serviço e habilitá-lo.

$ sudo mv dcrd.service /etc/systemd/system/
$ sudo systemctl enable dcrd.service 
Created symlink /etc/systemd/system/multi-user.target.wants/dcrd.service → /etc/systemd/system/dcrd.service.

Sempre que o sistema for reiniciado o serviço do dcrd será requerido para inicialização pelo modo ‘multi-user’ (WantedBy) após a inicialização do serviço de rede (After) e será iniciado (ExecStart) com poderes do usuário (User) e do grupo (Group) se esses parâmetros forem especificados.

3. Execução

Depois que o serviço é habilitado através do systemctl, já é possível verificar seu status:

$ sudo systemctl status dcrd.service 
● dcrd.service - The full node blockchain server of Decred network
   Loaded: loaded (/etc/systemd/system/dcrd.service; enabled; vendor preset: enabled)
   Active: inactive (dead)
     Docs: http://decred.org/

Para iniciar o serviço e verificar sua mudança de status, que aparece na linha ‘Active: active (running)’:

$ sudo systemctl start dcrd.service 
$ sudo systemctl status dcrd.service 
● dcrd.service - The full node blockchain server of Decred network
   Loaded: loaded (/etc/systemd/system/dcrd.service; enabled; vendor preset: enabled)
   Active: active (running) since Fri 2018-05-04 21:36:47 WEST; 2s ago
     Docs: http://decred.org/
 Main PID: 18525 (dcrd)
    Tasks: 8 (limit: 19660)
   CGroup: /system.slice/dcrd.service
           └─18525 /opt/decred/dcrd

May 04 21:36:47 fullnode systemd[1]: Started The full node blockchain server of Decred network.
May 04 21:36:47 fullnode dcrd[18525]: 2018-05-04 21:36:47.655 [INF] DCRD: Version 1.1.2+release (Go version go1.9.2)
May 04 21:36:47 fullnode dcrd[18525]: 2018-05-04 21:36:47.689 [INF] DCRD: Home dir: /home/dcrduser/.dcrd
May 04 21:36:47 fullnode dcrd[18525]: 2018-05-04 21:36:47.699 [INF] DCRD: Loading block database from '/opt/blockchain/dcrd_data/mainnet/blockchain'
May 04 21:36:48 fullnode dcrd[18525]: 2018-05-04 21:36:48.229 [INF] DCRD: Block database loaded
May 04 21:36:48 fullnode dcrd[18525]: 2018-05-04 21:36:48.253 [INF] INDX: Exists address index is enabled
May 04 21:36:49 fullnode dcrd[18525]: 2018-05-04 21:36:49.107 [INF] STKE: Stake database version 1 loaded
May 04 21:36:49 fullnode dcrd[18525]: 2018-05-04 21:36:49.184 [INF] CHAN: Blockchain database version 2 loaded
May 04 21:36:49 fullnode dcrd[18525]: 2018-05-04 21:36:49.184 [INF] CHAN: Chain state: height 232705, hash 00000000000000000b831418b8beff661c
lines 1-18/18 (END)

Para se certificar que o serviço do dcrd está sendo executado com o usuário normal:

$ ps -aux | grep dcrd

Para terminar a execução do serviço e verificar a mudança de status, mostrada na linha ‘Active: inactive (dead)’:

$ sudo systemctl stop dcrd.service 
$ sudo systemctl status dcrd.service 
● dcrd.service - The full node blockchain server of Decred network
   Loaded: loaded (/etc/systemd/system/dcrd.service; enabled; vendor preset: enabled)
   Active: inactive (dead) since Sat 2018-05-05 17:42:18 WEST; 1s ago
     Docs: http://decred.org/
  Process: 22041 ExecStop=/opt/decred/dcrctl stop (code=exited, status=0/SUCCESS)
  Process: 18525 ExecStart=/opt/decred/dcrd (code=exited, status=0/SUCCESS)
 Main PID: 18525 (code=exited, status=0/SUCCESS)

May 05 17:42:18 fullnode dcrd[18525]: 2018-05-05 17:42:18.752 [WRN] SRVR: Server shutting down
May 05 17:42:18 fullnode dcrd[18525]: 2018-05-05 17:42:18.759 [WRN] RPCS: RPC server shutting down
May 05 17:42:18 fullnode dcrd[18525]: 2018-05-05 17:42:18.770 [INF] RPCS: RPC server shutdown complete
May 05 17:42:18 fullnode dcrd[18525]: 2018-05-05 17:42:18.771 [INF] BMGR: Block manager shutting down
May 05 17:42:18 fullnode dcrd[18525]: 2018-05-05 17:42:18.771 [INF] AMGR: Address manager shutting down
May 05 17:42:18 fullnode dcrd[18525]: 2018-05-05 17:42:18.776 [INF] SRVR: Server shutdown complete
May 05 17:42:18 fullnode dcrd[18525]: 2018-05-05 17:42:18.776 [INF] DCRD: Gracefully shutting down the database...
May 05 17:42:18 fullnode dcrd[18525]: 2018-05-05 17:42:18.797 [INF] DCRD: Received signal (terminated).  Already shutting down...
May 05 17:42:18 fullnode dcrd[18525]: 2018-05-05 17:42:18.812 [INF] DCRD: Shutdown complete
May 05 17:42:18 fullnode systemd[1]: Stopped The full node blockchain server of Decred network.

Se o dcrd for terminado logo após seu início, enquanto ainda estiver carregando a blockchain, é possível que ocorra timeout em seu término, fazendo com que o status mostrado após a execução do comando sudo systemctl stop dcrd.service seja de falha. Isso ocorre porque o dcrd trava um pouquinho enquanto carrega a blockchain e não responde comandos RPC nesse início. Por isso não processará o comando enviado pelo dcrctl, sendo terminado via SIGKILL pelo sistema.

Para fazer alterações no arquivo dcrd.service é necessário primeiro desabilitar o serviço para então reabilitá-lo após as alterações.

$ sudo systemctl disable dcrd.service 
(...)
$ sudo systemctl enable dcrd.service 

4. Referências

Debian Wiki: Systemd
Debian Man pages: Systemctl
Fedora Project: Systemd