Executar programas automaticamente no arranque do servidor (systemd e cron)

Publicado a Atualizado a 6 min de leitura

As suas aplicações, servidores de jogos e scripts arrancam sozinhos depois de cada reinício: com uma unidade de serviço systemd, o padrão atual, ou em alternativa com uma entrada cron @reboot.

Voltar a arrancar todos os serviços à mão depois de cada reinício do servidor: isso custa tempo e mais cedo ou mais tarde acaba por correr mal. O Linux traz um mecanismo próprio exatamente para isso. Neste guia mostramos como pode executar automaticamente as suas próprias aplicações, servidores de jogos, bots ou scripts no arranque do servidor.

Vamos percorrer dois caminhos: uma unidade de serviço systemd, a solução habitual hoje em dia, e a via mais antiga através de uma entrada cron com @reboot. Ambos funcionam independentemente da distribuição, ou seja, tanto em Debian e Ubuntu como em AlmaLinux e Rocky Linux.

systemd ou cron: que caminho escolher?

O systemd é o padrão para serviços em todas as distribuições Linux atuais. Uma entrada cron com @reboot também arranca a sua aplicação, mas não sabe fazer mais nada além disso.

CaracterísticaUnidade systemdcron com @reboot
Arranque com o sistemasimsim
Reinício depois de uma falhasim, automaticamentenão
Consultar o estadosim, através do systemctlnão
Registo das saídassim, no journalsó se as redirecionar por conta própria
Ordem de arranque controlávelsim, por exemplo depois da redeapenas de forma grosseira, com sleep

Para tudo o que deve correr de forma permanente, a unidade systemd é a melhor escolha. A entrada cron continua a ser uma solução de recurso rápida, reservada a comandos simples executados uma única vez.

Requisitos

  • Acesso root ao seu vServer ou servidor root através de SSH.
  • Um script de arranque ou programa que já arranque corretamente na linha de comandos. Teste-o primeiro à mão, antes de o automatizar.
  • O caminho absoluto para esse script. Os caminhos relativos não funcionam de forma fiável durante o arranque do sistema.

Criar uma unidade de serviço systemd

As unidades próprias ficam em /etc/systemd/system/ e terminam em .service. Crie o ficheiro:

nano /etc/systemd/system/meuservico.service

Um esqueleto simples e pronto a usar tem este aspeto:

[Unit]
Description=O meu próprio serviço
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
User=meuutilizador
WorkingDirectory=/opt/meuservico
ExecStart=/bin/bash /opt/meuservico/start.sh
Restart=on-failure
RestartSec=10

[Install]
WantedBy=multi-user.target

O que significa cada linha

  • Description: o nome em texto simples que o systemctl status apresenta.
  • After e Wants: o serviço só arranca quando a rede está disponível. Assim dispensa o truque do sleep que se conhece do cron.
  • Type=simple: o programa mantém-se a correr em primeiro plano. Se o seu script de arranque passar sozinho para segundo plano, precisa antes de Type=forking e de uma indicação PIDFile.
  • User: o utilizador com o qual o serviço corre. Nunca deixe aplicações a correr como root sem necessidade.
  • WorkingDirectory: substitui o cd de um script de arranque.
  • Restart=on-failure: o systemd reinicia o serviço depois de uma falha. Com Restart=always faz o mesmo também quando o programa termina normalmente.
  • WantedBy=multi-user.target: garante que o serviço é iniciado com o arranque normal do sistema.

Ativar e testar o serviço

Depois de cada alteração a um ficheiro de unidade, o systemd tem de o voltar a ler. De seguida ativa o serviço para o arranque do sistema e inicia-o logo:

systemctl daemon-reload
systemctl enable --now meuservico.service

Para verificar se está tudo a correr:

systemctl status meuservico.service

As saídas da aplicação vão parar ao journal. Com o comando seguinte acompanha-as em direto, o que é a via mais rápida para diagnosticar um problema:

journalctl -u meuservico.service -f

Para parar, reiniciar ou desativar de forma permanente:

systemctl stop meuservico.service
systemctl restart meuservico.service
systemctl disable meuservico.service

Exemplo: arrancar automaticamente um servidor TeamSpeak 3

O script de arranque fornecido pelo TeamSpeak envia-se a si próprio para segundo plano e cria um ficheiro PID. Por isso, aqui o correto é Type=forking:

[Unit]
Description=TeamSpeak 3 Server
After=network-online.target
Wants=network-online.target

[Service]
Type=forking
User=teamspeak
WorkingDirectory=/home/teamspeak
ExecStart=/home/teamspeak/ts3server_startscript.sh start
ExecStop=/home/teamspeak/ts3server_startscript.sh stop
PIDFile=/home/teamspeak/ts3server.pid
Restart=on-failure
RestartSec=15

[Install]
WantedBy=multi-user.target

Adapte o nome de utilizador e o diretório à sua instalação. É importante que o utilizador indicado seja mesmo o dono do diretório.

Exemplo: servidor de jogos ou bot através de um script de arranque

Para Minecraft, ARK, Arma 3, servidores LinuxGSM ou um bot escrito por si, a variante simples chega em regra. O serviço corre em primeiro plano e o systemd encarrega-se da monitorização e do reinício:

[Unit]
Description=Servidor de jogos
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
User=gameserver
WorkingDirectory=/home/gameserver/server
ExecStart=/bin/bash /home/gameserver/server/start.sh
Restart=always
RestartSec=15

[Install]
WantedBy=multi-user.target

Se vários serviços arrancarem ao mesmo tempo e se atrasarem uns aos outros, distribua o arranque por valores diferentes em RestartSec ou complete After= com o nome da unidade que deve correr primeiro.

Alternativa: arranque automático através do cron com @reboot

Se pretende apenas executar um único comando no arranque e não precisa de monitorização, uma entrada cron chega. Defina primeiro o editor e abra a crontab:

export VISUAL=nano; crontab -e

Introduza aí uma linha com @reboot:

@reboot sleep 60 && cd /<DIRETORIO-DO-SCRIPT>/ && bash <O-SEU-SCRIPT>.sh

O @reboot faz com que o comando seja executado uma vez em cada arranque do sistema. A parte sleep 60 espera 60 segundos, para que a rede e a base de dados estejam prontas antes. Depois o comando muda para o diretório do seu script e inicia-o.

Um exemplo para um servidor de voz que deve correr sob um utilizador próprio:

@reboot sleep 45 && cd /home/<DIRETORIO-TEAMSPEAK>/ && sudo -u <UTILIZADOR-TEAMSPEAK> bash ts3server_startscript.sh start

Se introduzir várias linhas, dê a cada uma um valor sleep diferente (no mínimo 45), para que os serviços não arranquem todos ao mesmo tempo. O valor é indicado em segundos.

Erros frequentes

  • O serviço não arranca, apesar de funcionar à mão: na maioria das vezes falta um caminho absoluto. Numa unidade, tal como no cron, a variável de ambiente PATH está definida de forma muito reduzida, por isso escreva sempre /bin/bash /caminho/completo/script.sh.
  • "Unit not found" logo depois de criar o ficheiro: esqueceu-se do systemctl daemon-reload.
  • O serviço termina de imediato: o programa passa para segundo plano. Use Type=forking com o PIDFile adequado ou inicie o programa em modo de primeiro plano.
  • Erro de permissões no arranque: o utilizador indicado em User= não pode aceder ao diretório. Verifique o proprietário com ls -la.
  • Depois do arranque não corre nada: o serviço foi iniciado, mas não ativado. systemctl enable é o passo que o inscreve de forma permanente.

Para terminar, o melhor teste de todos: reinicie o servidor uma vez com reboot e verifique depois com systemctl status se todos os serviços correm como esperado.

Perguntas frequentes

O que é melhor: systemd ou cron com @reboot?
Para tudo o que deve correr de forma permanente, o systemd é claramente superior. Reinicia a aplicação depois de uma falha, mostra o estado e regista as saídas. Uma entrada cron limita-se a executar o comando uma vez no arranque.
Onde coloco a minha própria unidade systemd?
Os ficheiros de unidade próprios pertencem a /etc/systemd/system/ e terminam em .service. Depois de cada alteração tem de executar systemctl daemon-reload, caso contrário o systemd não conhece o ficheiro.
O meu serviço funciona à mão, mas não arranca com o sistema. Porquê?
Na maioria das vezes falta um caminho absoluto, porque a variável de ambiente PATH está definida de forma muito reduzida no arranque do sistema. O segundo motivo mais frequente: o serviço foi apenas iniciado, nunca ativado de forma permanente com systemctl enable.
Como vejo as saídas do meu serviço?
O systemd escreve tudo no journal. Com journalctl -u meuservico.service -f acompanha as saídas em direto, o que é a via mais rápida para diagnosticar um problema.
Ainda preciso de screen ou tmux para um servidor de jogos?
Não. O systemd mantém o processo a correr, regista a saída e reinicia-o automaticamente depois de uma falha. Para o simples funcionamento contínuo, o screen e o tmux tornam-se dispensáveis.

Arranque automático systemd Crontab Linux Servidor de jogos TeamSpeak3 Arranque do servidor