Carregando...
Linux

Usando o systemd no Linux e criando seus próprios serviços

Como podemos fazer que um programa se inicie automaticamente no Linux? Como configuramos para ele reiniciar caso o software caia? O systemd (system daemon) do Linux faz todo esse trabalho difícil para nós.

Partindo para nomes técnicos, o nome dos softwares que se iniciam automaticamente por trás dos panos e geralmente não tem interface gráfica é chamado de serviço ou service.

Ao iniciar o Linux ou instalar softwares, são criados automaticamente vários serviços, e você pode acessá-los com os comandos systemctl (use *sudo* se você estiver mexendo com serviços do sistema):

# Para descobrir todos os serviços instalados e se estão parados ou rodando
systemctl list-unit-files

# Para ver o log e o estado de um serviço específico
systemctl status nome-do-servico

# Para parar um serviço
systemctl stop nome-do-servico

# Para iniciar um serviço
systemctl start nome-do-servico

# Para reiniciar um serviço
systemctl restart nome-do-servico

# Para fazer um serviço iniciar automaticamente quando o computador ligar
systemctl enable nome-do-servico

# Para impedir que um serviço inicie automaticamente quando o computador ligar
systemctl disable nome-do-servico

Criando seu próprio serviço, fazendo um software ser iniciado automaticamente ao ligar o computador

Eis um exemplo de arquivo de serviço para o systemd no Ubuntu 16.04 (ATENÇÃO! Em versões diferentes do próprio Ubuntu esse arquivo pode mudar e precisar de comandos diferentes para executar uma mesma tarefa).

O nome do arquivo deve terminar em .service, tipo seu-servico.service

O arquivo deve ser salvo na pasta /etc/systemd/system

[Unit] 
Description=Seu serviço customizado - Versão 1.0 
After=network.target 

[Service] 
Type=simple 
Restart=always 
RestartSec=1 
StartLimitInterval=0 
ExecStart=/usr/bin/python3 /home/ubuntu/codigo/hello.py 
WorkingDirectory=/home/my-user/hello-logs/
User=my-user

[Install]
WantedBy=multi-user.target

Depois de alterar um serviço que já existe, faça o systemd recarregar a configuração dos serviços

systemctl daemon-reload

Veja se seu serviço foi instalado corretamente usando

systemctl status seu-servico.service
# ou
systemctl status seu-servico

Onde ficam os arquivos responsáveis por iniciar serviços?

Os serviços criados automaticamente por softwares baixados via apt install (por exemplo) são salvos em

/lib/systemd/system/ no Debian e no Ubuntu
/usr/lib/systemd/ em outras distribuições do Linux

Os serviços customizados, criados por você ou por um administrador do sistema, podem ser colocados em

/etc/systemd/system/

Uma lista completa da localização dos arquivos de serviço do systemd está aqui.

Costumo deixar que o dono dos serviços seja o usuário root, e a permissão 644.

chown root:root servico-teste.service 
chmod 644 servico-teste.service

Executando o Python dentro de um Ambiente Virtual (Virtual Environment)

Dentro de [Service] coloque

[Service]
...
...
Environment="PYTHONPATH=/home/ubuntu/anaconda/envs/intel/lib/python3.6/site-packages"
...

Vendo logs ou saídas do systemd usando journalctl

# Para filtrar pelo nome do serviço
journalctl -u nome-do-servico.service

# Para filtrar pelo nome do serviço usando grep
journalctl | grep nome_do-servico

# Para ver os logs do serviço em tempo real (também chamado de tail)
journalctl --follow -u nome-do-servico.service

Systemd sem sudo (nível de usuário)

É possível criar serviços no systemd sem precisar de sudo. Isso se chama user lingering. Para instalar basta rodar os comandos:

# Instalando o libpam-systemd para corrigir bug de acesso ao systemd --user via ssh. Sessões via ssh normalmente não conseguem executar o comando systemd --user ..., mas com esse pacote os bugs são resolvidos
sudo apt install libpam-systemd
# Enable/disable user lingering for one or more users. If enabled for a specific user, a user manager is spawned for the user at boot and kept around after logouts. This allows users who are not logged in to run long-running services. Takes one or more user names or numeric UIDs as argument. If no argument is specified, enables/disables lingering for the user of the session of the caller.
sudo loginctl enable-linger USERNAME

Os arquivos de serviço a nivel de usuário estão em

~/.config/systemd/user/

Para executar comandos basta usar:

systemctl --user status seu-servico
systemctl --user stop seu-servico
systemctl --user start seu-servico
systemctl --user enable seu-servico
systemctl --user disable seu-servico

Variáveis usadas em um arquivo do tipo .service

  • %n: Anywhere where this appears in a template file, the full resulting unit name will be inserted.
  • %N: This is the same as the above, but any escaping, such as those present in file path patterns, will be reversed.
  • %p: This references the unit name prefix. This is the portion of the unit name that comes before the @ symbol.
  • %P: This is the same as above, but with any escaping reversed.
  • %i: This references the instance name, which is the identifier following the @ in the instance unit. This is one of the most commonly used specifiers because it will be guaranteed to be dynamic. The use of this identifier encourages the use of configuration significant identifiers. For example, the port that the service will be run at can be used as the instance identifier and the template can use this specifier to set up the port specification.
  • %I: This specifier is the same as the above, but with any escaping reversed.
  • %f: This will be replaced with the unescaped instance name or the prefix name, prepended with a /.
  • %c: This will indicate the control group of the unit, with the standard parent hierarchy of /sys/fs/cgroup/ssytemd/ removed.
  • %u: The name of the user configured to run the unit.
  • %U: The same as above, but as a numeric UID instead of name.
  • %H: The host name of the system that is running the unit.
  • %%: This is used to insert a literal percentage sign.

Referências

Tutorial: Criando um serviço no linux com o systemd
https://medium.com/@benmorel/creating-a-linux-service-with-systemd-611b5c8b91d6

Tutorial 2: Criando um serviço no linux com systemd
https://www.devdungeon.com/content/creating-systemd-service-files

Significado dos parêmetros usados no arquivo .service
https://www.digitalocean.com/community/tutorials/understanding-systemd-units-and-unit-files

Documentação oficial do Linux sobre os scripts de inicialização em /etc/init.d
http://refspecs.linuxbase.org/LSB_3.0.0/LSB-PDA/LSB-PDA/initscrcomconv.html

Cinco maneiras diferentes de rodar um programa automaticamente no Linux
https://www.dexterindustries.com/howto/run-a-program-on-your-raspberry-pi-at-startup/

Criando um systemd com timer (substituto do cron)
https://medium.com/horrible-hacks/using-systemd-as-a-better-cron-a4023eea996d

Documentação do Redhat Linux 7 sobre systemd
https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/7/html/system_administrators_guide/sect-managing_services_with_systemd-unit_files

Definindo usuários ao rodar um serviço
https://askubuntu.com/questions/676007/how-do-i-make-my-systemd-service-run-via-specific-user-and-start-on-boot

Compreendendo SystemD
https://www.digitalocean.com/community/tutorials/understanding-systemd-units-and-unit-files

Rodando SystemD como usuário
https://superuser.com/questions/1025091/start-a-systemd-user-service-at-boot
https://unix.stackexchange.com/questions/438064/failed-to-determine-supplementary-groups-operation-not-permitted

Documentação do comando para habilitar systemd a nivel de usuário
https://www.freedesktop.org/software/systemd/man/loginctl.html#enable-linger%20USER%E2%80%A6

Deixe uma resposta

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *