Objetivos de Systemd Explicados: Gestión Efectiva de Estados de Arranque y Niveles de Ejecución

Comprende los objetivos de systemd, equivalentes de niveles de ejecución, estados de arranque predeterminados, aislamiento, modos de rescate y gráfico.

Objetivos de Systemd Explicados: Gestión Efectiva de Estados de Arranque y Niveles de Ejecución

Los objetivos de systemd son estados del sistema con nombre. Un objetivo puede representar un arranque normal de servidor, un escritorio gráfico, un shell de rescate, un apagado o un grupo personalizado de servicios que deseas iniciar juntos. Si vienes de sistemas Linux más antiguos, los objetivos son el reemplazo de systemd para las partes de los niveles de ejecución que la gente realmente usaba, pero son más flexibles porque se construyen a partir de dependencias en lugar de solo números.

Normalmente te encuentras con objetivos cuando un servidor arranca en el modo incorrecto, un gestor de pantalla de escritorio no se inicia, o una guía de recuperación te dice que ingreses rescue.target. Conocer algunos comandos hace que esas situaciones sean mucho menos misteriosas.

La Evolución de los Niveles de Ejecución a los Objetivos de Systemd

Históricamente, los sistemas Linux usaban un concepto llamado niveles de ejecución para definir el estado operativo del sistema durante el arranque y la ejecución. Un nivel de ejecución era un identificador numérico (0-6) que dictaba qué servicios se iniciaban o detenían. Por ejemplo, el nivel de ejecución 3 normalmente significaba un modo de texto multiusuario, mientras que el nivel de ejecución 5 indicaba un entorno multiusuario gráfico. Este sistema, aunque funcional, tenía limitaciones:

  • Rigidez: Los niveles de ejecución a menudo se definían de manera fija o específica de la distribución, lo que dificultaba personalizar el conjunto exacto de servicios activos para un estado dado.
  • Dependencias Implícitas: Las dependencias entre servicios a menudo se gestionaban indirectamente a través de asignaciones de niveles de ejecución, lo que llevaba a posibles conflictos o servicios omitidos.
  • Falta de Granularidad: El sistema numérico carecía de claridad descriptiva, lo que dificultaba entender el estado previsto del sistema.

Los objetivos de systemd abordan estas limitaciones proporcionando un enfoque más explícito, impulsado por dependencias y descriptivo. En lugar de números abstractos, los objetivos tienen nombres significativos (por ejemplo, multi-user.target, graphical.target) que indican claramente el estado previsto del sistema. Las dependencias se definen explícitamente dentro de los archivos de unidad, asegurando que todos los componentes necesarios se inicien en el orden correcto.

El mapeo aproximado se ve así en muchos sistemas systemd:

Nivel de ejecución tradicional Equivalente común en systemd Significado
0 poweroff.target Apagar y desconectar
1 rescue.target Modo de rescate de un solo usuario
3 multi-user.target Modo texto/servidor multiusuario
5 graphical.target Modo multiusuario más inicio de sesión gráfico
6 reboot.target Reiniciar

Trata esto como una ayuda de traducción, no como una ley. El comportamiento de los niveles de ejecución variaba entre distribuciones, y los objetivos de systemd pueden expresar relaciones que los niveles de ejecución antiguos no podían.

Comprendiendo los Objetivos de Systemd

Un objetivo de systemd es en sí mismo un tipo de unidad. Cuando se activa una unidad objetivo, systemd intenta activar todas las unidades que están listadas como dependencias dentro del archivo de unidad de ese objetivo. Esto crea un efecto en cascada, asegurando que todos los servicios, dispositivos y otros componentes necesarios se pongan en línea para alcanzar el estado del sistema deseado.

Características Clave de los Objetivos de Systemd:

  • Gestión de Dependencias: Los objetivos definen qué otras unidades deben estar activas para que el objetivo se considere alcanzado. Este es el núcleo de su poder.
  • Puntos de Sincronización: Actúan como puntos de sincronización durante el proceso de arranque. El sistema no procederá a la siguiente etapa hasta que el objetivo actual esté completamente inicializado.
  • Nombres Descriptivos: Los objetivos se nombran de manera descriptiva, lo que facilita entender el estado previsto del sistema (por ejemplo, rescue.target, poweroff.target).

Los objetivos generalmente no ejecutan código de larga duración por sí mismos. Agrupan otras unidades. Puedes inspeccionar esa agrupación con:

systemctl list-dependencies multi-user.target
systemctl list-dependencies graphical.target

Esta es una buena manera de responder: "¿Por qué este servicio se inicia al arrancar?" Si la unidad aparece en el árbol de dependencias para el objetivo predeterminado, está siendo atraída desde algún lugar.

Objetivos Comunes de Systemd

Systemd viene con un conjunto de objetivos predefinidos diseñados para cubrir estados comunes del sistema. Comprender estos es clave para gestionar tu sistema.

multi-user.target

Este es uno de los objetivos más fundamentales. Representa un sistema multiusuario completamente funcional con redes habilitadas pero sin un gestor de inicio de sesión gráfico o entorno de escritorio. Este es típicamente el objetivo predeterminado para servidores.

  • Propósito: Proporcionar un entorno estable para ejecutar servicios y permitir que múltiples usuarios inicien sesión a través de consolas de texto o SSH.
  • Dependencias: Generalmente incluye unidades para redes, servicios del sistema y avisos de inicio de sesión en consola.

Para servidores sin cabeza, multi-user.target suele ser el predeterminado correcto. Te da SSH y servicios normales sin gastar recursos en un gestor de pantalla.

graphical.target

Este objetivo representa un sistema multiusuario completamente funcional con un entorno de escritorio gráfico listo para la interacción del usuario. Típicamente es un dependiente de multi-user.target y añade los componentes necesarios para una sesión gráfica.

  • Propósito: Iniciar un gestor de pantalla gráfico (como GDM, LightDM, SDDM) y el entorno de escritorio asociado.
  • Dependencias: Comúnmente atrae el comportamiento de multi-user.target y añade unidades para un gestor de pantalla y componentes de sesión gráfica.

Si una estación de trabajo arranca a una pantalla negra pero SSH aún funciona, compara estos:

systemctl get-default
systemctl status display-manager.service
journalctl -u display-manager.service -b

El objetivo predeterminado te dice lo que el sistema intentó alcanzar. Los registros del gestor de pantalla te dicen por qué la capa gráfica se inició o no.

rescue.target

Este objetivo proporciona un entorno mínimo de un solo usuario. Se utiliza principalmente para mantenimiento y recuperación del sistema. Levanta el sistema básico y un shell de root, pero típicamente no inicia redes ni servicios multiusuario.

  • Propósito: Proporcionar un entorno seguro para que los administradores del sistema realicen tareas de mantenimiento sin interferencias de otros servicios.
  • Dependencias: Conjunto mínimo de componentes esenciales del sistema y un shell de root. La red a menudo no está disponible a menos que la inicies manualmente.

emergency.target

Este es incluso más mínimo que rescue.target. Lleva el sistema a un solo sistema de archivos de solo lectura y un shell de root. Está destinado a situaciones de emergencia graves donde incluso los servicios básicos podrían ser problemáticos.

  • Propósito: Para recuperación crítica del sistema cuando incluso rescue.target podría no ser apropiado.
  • Dependencias: Solo los componentes más esenciales del sistema y un shell de root. El sistema de archivos raíz puede montarse como solo lectura dependiendo de la falla y la distribución.

reboot.target, poweroff.target, halt.target

Estos son objetivos especiales utilizados para apagar o reiniciar el sistema. Cuando systemd activa uno de estos objetivos, detiene todos los servicios en ejecución y luego realiza la acción especificada (reiniciar, apagar o detener).

  • Propósito: Apagar o reiniciar el sistema de manera ordenada.
  • Dependencias: Típicamente dependen de servicios que necesitan detenerse antes de que el sistema pueda apagarse.

Gestionando Objetivos de Systemd

Systemd proporciona varias herramientas de línea de comandos para interactuar con los objetivos. La herramienta principal es systemctl.

Visualizando Objetivos Actuales y Predeterminados

Para ver en qué objetivo se está ejecutando actualmente el sistema y a qué objetivo se dirige por defecto al arrancar, usa:

systemctl status

Este comando proporciona una gran cantidad de información, incluyendo el objetivo activo. Para consultar específicamente el objetivo predeterminado:

systemctl get-default

Para ver todos los objetivos disponibles:

systemctl list-unit-files --type=target

Para ver unidades objetivo activas, usa:

systemctl list-units --type=target

La diferencia es la misma que con los servicios: list-unit-files muestra los archivos objetivo que systemd conoce, mientras que list-units muestra los objetivos actualmente cargados o activos en el sistema en ejecución.

Cambiando el Objetivo Predeterminado

Si deseas que tu sistema arranque en un objetivo diferente por defecto (por ejemplo, de gráfico a multiusuario, o viceversa), puedes usar systemctl set-default:

Para establecer el predeterminado en objetivo gráfico (común en sistemas de escritorio):

sudo systemctl set-default graphical.target

Para establecer el predeterminado en objetivo multiusuario (común en servidores):

sudo systemctl set-default multi-user.target

Importante: Cambiar el objetivo predeterminado solo tendrá efecto en el próximo reinicio.

Internamente, esto cambia el enlace simbólico default.target. Puedes inspeccionarlo directamente si estás depurando una imagen de arranque rota:

systemctl get-default
ls -l /etc/systemd/system/default.target

Cambiando a un Objetivo (Sin Reiniciar)

Puedes cambiar el sistema a un objetivo diferente inmediatamente sin reiniciar. Esto es útil para probar o cambiar temporalmente el estado del sistema. Usa el comando systemctl isolate:

Para cambiar al objetivo gráfico:

sudo systemctl isolate graphical.target

Para cambiar al objetivo multiusuario:

sudo systemctl isolate multi-user.target

Precaución: systemctl isolate es un comando poderoso. Aislar a un objetivo como rescue.target o emergency.target detendrá la mayoría de los servicios en ejecución. Asegúrate de entender las implicaciones antes de usarlo. Podrías perder conectividad de red o tu sesión gráfica.

En un servidor remoto, ten especial cuidado con isolate rescue.target o isolate emergency.target. Podrías perder SSH y necesitar acceso a la consola a través de tu proveedor de nube, hipervisor o máquina física. Si solo necesitas detener el escritorio gráfico en una estación de trabajo, aislar a multi-user.target es menos drástico que saltar directamente al modo de rescate.

Cómo se Relacionan los Objetivos con los Archivos de Unidad

Los objetivos se implementan como archivos de unidad, típicamente ubicados en /usr/lib/systemd/system/ o /etc/systemd/system/. Un archivo de unidad objetivo (por ejemplo, graphical.target) especifica dependencias en otras unidades, incluyendo otros objetivos y servicios.

Un archivo de unidad graphical.target típico podría verse así (simplificado):

[Unit]
Description=Graphical multi-user system
Documentation=man:systemd.special(7)
# This target is intended to be a prerequisite for the graphical login manager.
# It's the target that the system will boot into if not otherwise specified.
Wants=display-manager.service
Before=shutdown.target

[Install]
Alias=default.target

Aquí:

  • Wants=display-manager.service: Indica que display-manager.service (el gestor de inicio de sesión real como GDM o LightDM) debe iniciarse si es posible. Esta es una dependencia más débil que Requires=.
  • Before=shutdown.target: Asegura que el entorno gráfico se detenga antes de que el sistema entre en el proceso de apagado.
  • Alias=default.target: Esto hace que graphical.target actúe como el predeterminado si default.target está vinculado a él (lo que suele ser el caso para sistemas de escritorio).

Creando Objetivos Personalizados

Aunque es menos común para el uso diario, puedes crear tus propios objetivos personalizados para definir estados específicos del sistema con conjuntos únicos de servicios.

Pasos para Crear un Objetivo Personalizado:

  1. Crea un archivo de unidad .target: Colócalo en /etc/systemd/system/ (por ejemplo, my-custom.target).
    [Unit]
    Description=My Custom Target
    
    [Install]
    WantedBy=multi-user.target # Or another appropriate target
    
  2. Crea archivos .service u otras unidades: Define los servicios y otras unidades que deben estar activas para tu objetivo personalizado.
  3. Añade dependencias: En el archivo de unidad de tu objetivo personalizado, usa Requires= o Wants= para especificar qué unidades deben o deberían iniciarse.
    [Unit]
    Description=My Custom Target
    Wants=service1.service
    Wants=service2.service
    After=service1.service service2.service
    
    [Install]
    WantedBy=multi-user.target
    
  4. Recarga systemd:
    
    

sudo systemctl daemon-reload 5. **Habilita/Inicia tu objetivo:** bash sudo systemctl start my-custom.target # Or to make it bootable sudo systemctl enable my-custom.target ```

Caso de Uso: Imagina un entorno de desarrollo donde necesitas servidores de base de datos y aplicaciones específicos ejecutándose. Podrías crear un dev-env.target que inicie estos servicios.

Los objetivos personalizados también son útiles para sistemas tipo electrodoméstico. Por ejemplo, una máquina quiosco podría tener un objetivo que inicie redes, un navegador, un watchdog local y un agente de registro, pero no el resto de una sesión de escritorio normal. Un servidor de laboratorio podría tener objetivos separados para una pila de prueba y una pila de demostración para que los operadores puedan iniciar un grupo conocido de servicios juntos.

Mejores Prácticas y Consejos

  • Comprende el Predeterminado: Conoce el objetivo predeterminado de tu sistema (graphical.target o multi-user.target) ya que dicta la experiencia inicial de arranque.
  • Usa isolate con Precaución: Ten cuidado al usar systemctl isolate, especialmente en sistemas de producción, ya que puede interrumpir servicios en ejecución.
  • Verifica las Dependencias: Si un servicio no se inicia, examina las dependencias del objetivo con el que está asociado usando systemctl list-dependencies <nombre_objetivo>.
  • Servidor vs. Escritorio: En servidores, multi-user.target es casi siempre preferido por seguridad y eficiencia de recursos. En escritorios, graphical.target es estándar.
  • Mantenimiento del Sistema: Para tareas que requieren mínima interferencia, rescue.target es útil. Para recuperación crítica, emergency.target está disponible.

Una Manera Práctica de Pensar en los Objetivos

Para la mayoría del trabajo de administración, solo necesitas un modelo mental corto:

systemctl get-default
systemctl set-default multi-user.target
systemctl isolate graphical.target
systemctl list-dependencies graphical.target

get-default te dice dónde se supone que debe arrancar la máquina. set-default cambia el próximo arranque. isolate cambia el estado actual y puede detener servicios fuera de ese estado. list-dependencies explica lo que un objetivo atrae.

Los objetivos no son solo niveles de ejecución renombrados. Son grupos de dependencias. Una vez que los tratas de esa manera, los problemas de arranque se vuelven más fáciles de razonar: encuentra el objetivo que el sistema intentó alcanzar, inspecciona los servicios que quería, luego arregla la unidad o dependencia que falló.