Carregando...
Linux

Usando o systemd no Linux – Como criar seus próprios serviços e daemons no Linux?

  • Como fazer um programa iniciar automaticamente no Linux após reiniciar o computador?
  • Caso aconteça algum erro no programa e ele pare de funcionar, como reinicia-lo automaticamente?

O programa systemd (system daemon) do Linux pode gerenciar tudo isso para nós.

Se você está no Windows e quer criar serviços, use o NSSM, veja esse outro artigo aqui no blog.

O SystemD é um gerenciador de Serviços ou Daemons. O que é Serviço ou Daemon? São softwares/programas/aplicativos que tem as características de ficarem ligados por longos tempos e não ter uma interface gráfica. Geralmente eles iniciam automaticamente quando o computador é ligado, e quem faz isso no Linux é o systemd.

Ao iniciar o Linux ou instalar certos 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
systemctl status nome-do-servico@subprocesso
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).

Nesse exemplo rodaremos um código em python 3.

O nome do arquivo deve terminar em .service (tipo seu-servico.service). O arquivo deve ser salvo na pasta /etc/systemd/system

sudo nano /etc/systemd/system/seu-servico.service

Conteúdo do arquivo:

[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

sudo systemctl daemon-reload

Veja se seu serviço foi instalado corretamente usando

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

Para excluir de vez um serviço que não quer ser apagado:

systemctl stop [servicename]
systemctl disable [servicename]
rm /etc/systemd/system/[servicename]
rm /etc/systemd/system/[servicename] # and symlinks that might be related
rm /usr/lib/systemd/system/[servicename] 
rm /usr/lib/systemd/system/[servicename] # and symlinks that might be related
systemctl daemon-reload
systemctl reset-failed

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:

Debian e Ubuntu:
/lib/systemd/system/

Outras distribuições:
/usr/lib/systemd/

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

Usando o systemd a nível de usuário, sem precisar de sudo!

É possível criar serviços no systemd sem precisar de sudo, essa função do systemd se chama user lingering. Ela já funciona por padrão no Debian ou no Ubuntu.

O user lingering faz o systemd criar automaticamente uma sessão para aquele usuário com o lingering ativo. Isso permite que esse usuário rode comandos assim que o computador seja iniciado, sem precisar pedir permissão ao super usuário (sudo).

Se você quiser usar o systemd a nivel de usuário via SSH é preciso instalar um pacote adicional. Aqui vai 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

# Criando um usuário
sudo adduser -m -s /bin/bash user-test

# Habilitando o systemd a nível de usuário para um usuário específico.
# Troque user-test pelo nome do usuario desejado.
sudo loginctl enable-linger USERNAME

Agora faça login com o usuário desejado e crie o diretório para armazenar os arquivos de serviço

# Logado com o usuário desejado, crie as pastas do systemd
mkdir -p ~/.config/systemd/user/

Se você quiser usar o systemd a nivel de usuário com um usuário trocado (utilizando o comando su –) é preciso fazer algumas configurações extras. Vamos alterar o arquivo ~/.profile e fazê-lo carregar uma variável de ambiente.

# Estando logado com o usuário comum (sem sudo), rode o seguinte comando
echo "export XDG_RUNTIME_DIR=/run/user/$UID" >> ~/.profile

Vamos também aplicar essa configuração para usuários futuros:

# Estando logado com o usuário root ou sudo, rode o seguinte comando
sudo sh -c "echo 'export XDG_RUNTIME_DIR=/run/user/$UID' >> /etc/skel/.profile"

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

~/.config/systemd/user/

Ao criar o serviço (arquivo .service), é importante utilizar os seguintes parametros:

#esse é uma dica:
[Service]
...
WorkingDirectory=/home/%u
...

#esse é importantíssimo!!
[Install]
WantedBy=default.target

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

# versões antigas do systemd
journalctl --user --user-unit=seu-servico
# versões novas do systemd
journalctl --user -u 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.

Fazendo serviço reiniciar de tempos em tempos

Você pode comandar o systemd a reiniciar seu serviço a cada X segundos, no exemplo abaixo fazemos reiniciar a cada 300 segundos (5 minutos):

[Service]
Type=simple
Restart=always
RuntimeMaxSec=300
RestartSec=1
StartLimitInterval=0

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

Reiniciando serviço de tempos em tempos com systemd
https://stackoverflow.com/a/50332245

User Lingering – SystemD

Tutorial muito bom sobre systemd user services
https://www.unixsysadmin.com/systemd-user-services/

Documentação Arch Linux sobre user lingering
https://wiki.archlinux.org/title/systemd/User#Reading_the_journal

Unixadmin – User Lingering
https://www.unixsysadmin.com/systemd-user-services/

RHEL Forum
https://access.redhat.com/solutions/4661741

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

Journalctl com systemd a nivel de usuário
https://serverfault.com/questions/806469/how-to-allow-a-user-to-use-journalctl-to-see-user-specific-systemd-service-logs

Usando o systemd para outros usuários
https://unix.stackexchange.com/questions/423632/systemctl-user-not-available-for-www-data-user

Arrumando arquivo .profile para o user lingering após troca de usuário via shell (sudo su -)
https://unix.stackexchange.com/questions/462845/how-to-apply-lingering-immedeately

3 comentários
Deixe um comentário

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