Service management: systemctl em scripts de deploy
1. Fundamentos do systemctl para Automação
O systemctl é a principal ferramenta de gerenciamento de serviços no systemd, presente na maioria das distribuições Linux modernas. Em scripts de deploy, dominar seus comandos básicos é essencial para automação confiável.
Comandos essenciais
# Comandos básicos de controle
systemctl start nginx
systemctl stop nginx
systemctl restart nginx
systemctl status nginx
Verificação de estado com exit codes
O verdadeiro poder do systemctl em scripts está nos comandos de verificação que retornam exit codes previsíveis:
#!/bin/bash
SERVICE="nginx"
# Verificar se o serviço está ativo
if systemctl is-active --quiet "$SERVICE"; then
echo "$SERVICE está rodando"
else
echo "$SERVICE não está ativo"
fi
# Verificar se está habilitado para iniciar com o sistema
if systemctl is-enabled --quiet "$SERVICE"; then
echo "$SERVICE está habilitado"
fi
# Verificar se falhou
if systemctl is-failed --quiet "$SERVICE"; then
echo "$SERVICE falhou - ação necessária!"
fi
2. Gerenciamento de Serviços em Deploy
Parada segura antes de atualizações
#!/bin/bash
deploy_app() {
local SERVICE="myapp"
local DEPLOY_DIR="/opt/myapp"
local BACKUP_DIR="/opt/backups/myapp"
echo "Iniciando deploy da aplicação..."
# Parar o serviço antes de atualizar
echo "Parando $SERVICE..."
systemctl stop "$SERVICE"
# Backup do diretório atual
echo "Criando backup..."
cp -r "$DEPLOY_DIR" "$BACKUP_DIR/$(date +%Y%m%d_%H%M%S)"
# Atualizar arquivos (rsync, scp, etc)
echo "Copiando novos arquivos..."
rsync -avz --delete ./dist/ "$DEPLOY_DIR/"
}
Reinicialização condicional após deploy
#!/bin/bash
restart_if_deployed() {
local SERVICE="myapp"
local HEALTH_ENDPOINT="http://localhost:8080/health"
# Verificar se arquivos foram alterados
if [ -f /tmp/deploy_complete.flag ]; then
echo "Deploy detectado. Reiniciando serviço..."
systemctl restart "$SERVICE"
rm -f /tmp/deploy_complete.flag
else
echo "Nenhum deploy novo detectado."
fi
}
Habilitar/desabilitar serviços automaticamente
#!/bin/bash
configure_service_autostart() {
local SERVICE="myapp"
local ENABLE=${1:-true}
if [ "$ENABLE" = true ]; then
systemctl enable "$SERVICE"
echo "$SERVICE habilitado para iniciar com o sistema"
else
systemctl disable "$SERVICE"
echo "$SERVICE desabilitado"
fi
}
3. Monitoramento e Validação de Saúde
Aguardando serviço ficar ativo
#!/bin/bash
wait_for_service() {
local SERVICE="$1"
local TIMEOUT=${2:-30}
local INTERVAL=2
local ELAPSED=0
echo "Aguardando $SERVICE ficar ativo..."
# systemctl is-active --wait (systemd 240+)
if systemctl is-active --wait "$SERVICE" 2>/dev/null; then
echo "$SERVICE está ativo"
return 0
fi
}
Polling com loops e timeouts para serviços lentos
#!/bin/bash
poll_service_health() {
local SERVICE="$1"
local TIMEOUT=${2:-60}
local SLEEP_INTERVAL=${3:-5}
local ELAPSED=0
while [ $ELAPSED -lt $TIMEOUT ]; do
if systemctl is-active --quiet "$SERVICE"; then
echo "Serviço $SERVICE ativo após ${ELAPSED}s"
return 0
fi
sleep "$SLEEP_INTERVAL"
ELAPSED=$((ELAPSED + SLEEP_INTERVAL))
done
echo "TIMEOUT: $SERVICE não ficou ativo em ${TIMEOUT}s"
return 1
}
Verificação de falhas e logs integrados
#!/bin/bash
check_service_failure() {
local SERVICE="$1"
local LOG_LINES=${2:-20}
if systemctl is-failed --quiet "$SERVICE"; then
echo "FALHA detectada em $SERVICE"
echo "Últimas $LOG_LINES linhas do journal:"
journalctl -u "$SERVICE" --no-pager -n "$LOG_LINES"
return 1
fi
return 0
}
4. Tratamento de Erros e Rollback
Captura de falhas
#!/bin/bash
safe_restart() {
local SERVICE="$1"
local BACKUP_DIR="$2"
if ! systemctl restart "$SERVICE"; then
echo "ERRO: Falha ao reiniciar $SERVICE"
return 1
fi
# Aguardar confirmação
sleep 5
if ! systemctl is-active --quiet "$SERVICE"; then
echo "ERRO: $SERVICE não está rodando após restart"
return 1
fi
return 0
}
Rollback automático
#!/bin/bash
deploy_with_rollback() {
local SERVICE="myapp"
local CURRENT_DIR="/opt/myapp"
local BACKUP_DIR="/opt/backups/myapp/latest"
# Tentar restart
echo "Reiniciando $SERVICE..."
if ! systemctl restart "$SERVICE"; then
echo "Falha no restart. Iniciando rollback..."
cp -r "$BACKUP_DIR"/* "$CURRENT_DIR/"
systemctl restart "$SERVICE"
if systemctl is-active --quiet "$SERVICE"; then
echo "Rollback concluído com sucesso"
return 0
else
echo "Rollback também falhou!"
return 1
fi
fi
echo "Deploy bem-sucedido"
}
Uso de trap para restaurar estado anterior
#!/bin/bash
cleanup() {
echo "Limpando e restaurando serviços..."
systemctl start "$SERVICE" 2>/dev/null || true
systemctl enable "$SERVICE" 2>/dev/null || true
}
trap cleanup EXIT ERR
deploy_script() {
local SERVICE="myapp"
systemctl stop "$SERVICE"
# ... operações de deploy ...
systemctl start "$SERVICE"
}
5. Manipulação de Unidades Customizadas
Criação e instalação de arquivos .service
#!/bin/bash
install_custom_service() {
local SERVICE_NAME="myapp"
local SERVICE_FILE="/etc/systemd/system/${SERVICE_NAME}.service"
cat > "$SERVICE_FILE" << EOF
[Unit]
Description=My Application Service
After=network.target
[Service]
Type=simple
User=myapp
WorkingDirectory=/opt/myapp
ExecStart=/usr/local/bin/myapp --config /etc/myapp/config.yml
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl enable "$SERVICE_NAME"
}
Validação de sintaxe
#!/bin/bash
validate_service_unit() {
local SERVICE_FILE="$1"
if [ ! -f "$SERVICE_FILE" ]; then
echo "Arquivo não encontrado: $SERVICE_FILE"
return 1
fi
# Validar sintaxe
if systemd-analyze verify "$SERVICE_FILE"; then
echo "Unidade válida"
return 0
else
echo "Unidade inválida - verifique o arquivo"
return 1
fi
}
6. Integração com Outras Ferramentas de Deploy
Exemplo completo: deploy + restart + healthcheck
#!/bin/bash
# Script completo de deploy
set -euo pipefail
SERVICE="myapp"
DEPLOY_DIR="/opt/myapp"
BINARY_SOURCE="/tmp/builds/myapp-latest"
HEALTHCHECK_URL="http://localhost:8080/health"
echo "=== Início do Deploy ==="
# 1. Parar serviço
echo "Parando $SERVICE..."
systemctl stop "$SERVICE"
# 2. Atualizar binário
echo "Copiando novo binário..."
cp "$BINARY_SOURCE" "$DEPLOY_DIR/myapp"
chmod +x "$DEPLOY_DIR/myapp"
# 3. Recarregar daemon se necessário
systemctl daemon-reload
# 4. Iniciar serviço
echo "Iniciando $SERVICE..."
systemctl start "$SERVICE"
# 5. Healthcheck
echo "Verificando saúde..."
for i in {1..12}; do
if systemctl is-active --quiet "$SERVICE"; then
if curl -sf "$HEALTHCHECK_URL" > /dev/null; then
echo "Deploy concluído com sucesso!"
exit 0
fi
fi
sleep 5
done
# 6. Rollback se falhar
echo "Falha no deploy. Realizando rollback..."
systemctl stop "$SERVICE"
cp "$DEPLOY_DIR/myapp.bak" "$DEPLOY_DIR/myapp"
systemctl start "$SERVICE"
exit 1
7. Boas Práticas e Segurança
Evitar restart sem verificação
#!/bin/bash
# EVITE:
systemctl restart nginx # Sem verificar se há alterações
# PREFIRA:
if [ -f /etc/nginx/nginx.conf ]; then
nginx -t && systemctl reload nginx || echo "Config inválida"
fi
Uso de systemctl --user para serviços não-root
#!/bin/bash
# Script para usuário não-root
deploy_user_service() {
local SERVICE="myapp-user"
local UNIT_DIR="${HOME}/.config/systemd/user"
mkdir -p "$UNIT_DIR"
cat > "$UNIT_DIR/${SERVICE}.service" << EOF
[Unit]
Description=User Service
[Service]
ExecStart=/usr/local/bin/myapp
Restart=on-failure
[Install]
WantedBy=default.target
EOF
systemctl --user daemon-reload
systemctl --user enable "$SERVICE"
systemctl --user start "$SERVICE"
}
Logging estruturado e notificações
#!/bin/bash
log_and_notify() {
local MESSAGE="$1"
local LEVEL="${2:-INFO}"
local TIMESTAMP=$(date '+%Y-%m-%d %H:%M:%S')
# Log estruturado
echo "[$TIMESTAMP] [$LEVEL] $MESSAGE" >> /var/log/deploy.log
# Notificação (exemplo com Slack)
if [ "$LEVEL" = "ERROR" ]; then
curl -sf -X POST -H "Content-type: application/json" \
--data "{\"text\":\"[$LEVEL] $MESSAGE\"}" \
"https://hooks.slack.com/services/YOUR/WEBHOOK/URL" 2>/dev/null || true
fi
}
deploy_service() {
log_and_notify "Iniciando deploy de $SERVICE" "INFO"
systemctl restart "$SERVICE" || log_and_notify "Falha no deploy" "ERROR"
}
Referências
- systemctl man page (official) — Documentação oficial completa do systemctl com todas as opções e exemplos de uso
- Creating and Modifying systemd Unit Files (Red Hat) — Guia oficial da Red Hat sobre criação e gerenciamento de unidades systemd
- systemd.service man page — Documentação detalhada sobre a diretiva [Service] em units do systemd
- Automating Deployments with systemd (DigitalOcean) — Tutorial prático sobre automação de serviços com systemctl em cenários de deploy
- systemd-analyze documentation — Documentação oficial da ferramenta de análise e validação de unidades systemd
- Journalctl: Working with Systemd Logs (Linuxize) — Guia completo sobre journalctl para diagnóstico e monitoramento de serviços systemd
- Bash Scripting Best Practices (Google Shell Style Guide) — Boas práticas de shell script do Google, aplicáveis a scripts de deploy com systemctl