Saltar al contenido principal

Capítulo 8.2 - Servicios Personalizados

Objetivos de Aprendizaje​

Al final de este capítulo, usted será capaz de:

  • Crear un archivo unit de systemd
  • Configurar un servicio personalizado
  • Comprender las secciones de un unit file
  • Gestionar las dependencias
  • Crear servicios para scripts

Estructura de un Unit File​

Ubicación​

# Sistema
/etc/systemd/system/

# Usuario
~/.config/systemd/user/

Prioridad:

  • /etc/systemd/system/ (sistema) > /usr/lib/systemd/system/ (paquetes)

Formato Básico​

[Unit]
Description=Descripción del servicio
After=network.target

[Service]
Type=simple
ExecStart=/ruta/al/comando
Restart=always

[Install]
WantedBy=multi-user.target

Secciones Principales​

[Unit]​

[Unit]
Description=Mi Servicio Personalizado
Documentation=man:mon-service(1)
After=network.target sshd.service
Before=some-service.service
Requires=network.target
Wants=sshd.service
Conflicts=old-service.service

Directivas:

  • Description: Descripción del servicio
  • After: Inicia después de estas unidades
  • Before: Inicia antes de estas unidades
  • Requires: Dependencia fuerte (falla si la dependencia falla)
  • Wants: Dependencia débil (continúa si la dependencia falla)
  • Conflicts: No puede ejecutarse al mismo tiempo

[Service]​

[Service]
Type=simple
ExecStart=/usr/local/bin/mon-script.sh
ExecStartPre=/bin/echo "Inicio"
ExecStartPost=/bin/echo "Iniciado"
ExecStop=/bin/echo "Detenido"
ExecReload=/bin/kill -HUP $MAINPID
Restart=always
RestartSec=10
User=monuser
Group=mongroup
WorkingDirectory=/var/lib/monservice
Environment="VAR1=valor1"
EnvironmentFile=/etc/monservice/env
StandardOutput=journal
StandardError=journal

Tipos:

  • simple: Comando principal (por defecto)
  • forking: Fork en segundo plano
  • oneshot: Ejecución única
  • notify: Notifica a systemd cuando está listo

Restart:

  • no: No reinicia
  • always: Siempre reiniciar
  • on-failure: Reiniciar si falla
  • on-success: Reiniciar si tiene éxito

[Install]​

[Install]
WantedBy=multi-user.target
Alias=monservice.service

Targets comunes:

  • multi-user.target: Modo multiusuario
  • graphical.target: Modo gráfico
  • default.target: Target por defecto

Ejemplos Prácticos​

Servicio Simple​

# /etc/systemd/system/mon-service.service
[Unit]
Description=Mi Servicio Simple
After=network.target

[Service]
Type=simple
ExecStart=/usr/local/bin/mon-script.sh
Restart=always
RestartSec=10
User=www-data
StandardOutput=journal
StandardError=journal

[Install]
WantedBy=multi-user.target

Activar:

sudo systemctl daemon-reload
sudo systemctl enable mon-service
sudo systemctl start mon-service

Servicio con Script​

#!/bin/bash
# /usr/local/bin/mon-script.sh
# Script de servicio

# Función de limpieza
cleanup() {
echo "Deteniendo el servicio"
# Limpieza...
exit 0
}

# Trap signals
trap cleanup SIGTERM SIGINT

# Bucle principal
while true; do
# Trabajo...
echo "Servicio activo: $(date)"
sleep 60
done

Unit file:

[Unit]
Description=Servicio con Script
After=network.target

[Service]
Type=simple
ExecStart=/usr/local/bin/mon-script.sh
Restart=always
RestartSec=5
StandardOutput=journal
StandardError=journal

[Install]
WantedBy=multi-user.target

Servicio Forking​

[Unit]
Description=Servicio Forking
After=network.target

[Service]
Type=forking
ExecStart=/usr/local/bin/daemon --daemonize
PIDFile=/var/run/daemon.pid
Restart=always

[Install]
WantedBy=multi-user.target

Servicio Oneshot​

[Unit]
Description=Script Oneshot
After=network.target

[Service]
Type=oneshot
ExecStart=/usr/local/bin/init-script.sh
RemainAfterExit=yes

[Install]
WantedBy=multi-user.target

Variables de Entorno​

En el Unit File​

[Service]
Environment="VAR1=valor1"
Environment="VAR2=valor2"
EnvironmentFile=/etc/monservice/env

Archivo de Entorno​

# /etc/monservice/env
VAR1=valor1
VAR2=valor2
VAR3="valor con espacios"

Gestión de Logs​

Journal systemd​

# Ver logs del servicio
sudo journalctl -u mon-service

# Seguir logs
sudo journalctl -u mon-service -f

# Logs recientes
sudo journalctl -u mon-service -n 50

# Desde fecha
sudo journalctl -u mon-service --since "2024-01-01"

Redirección​

[Service]
# Al journal (por defecto)
StandardOutput=journal
StandardError=journal

# A archivo
StandardOutput=file:/var/log/monservice.log
StandardError=file:/var/log/monservice-error.log

# Ignorar
StandardOutput=null
StandardError=null

Buenas Prácticas​

Estructura​

[Unit]
# Descripción clara
# Dependencias apropiadas

[Service]
# Tipo correcto
# User/Group no-root si es posible
# Restart apropiado
# Logging configurado

[Install]
# Target apropiado

Seguridad​

[Service]
# No usar root si es posible
User=serviceuser
Group=servicegroup

# Limitar capacidades
CapabilityBoundingSet=CAP_NET_BIND_SERVICE
NoNewPrivileges=true

# Chroot si es posible
RootDirectory=/var/lib/monservice

Resumen​

En este capítulo, usted ha aprendido:

Unit files: Estructura [Unit], [Service], [Install]
Tipos: simple, forking, oneshot, notify
Dependencias: After, Before, Requires, Wants
Restart: always, on-failure, never
Entorno: Environment, EnvironmentFile
Logs: journalctl, redirección a archivos
Práctica: Crear servicios para scripts y aplicaciones


Próximos Pasos​

Capítulo 8.3: Cron Avanzado y systemd Timers
Módulo 9: Seguridad del Sistema


Capítulo creado el: Diciembre 2024