Saltar al contenido

Linux: arranque y systemd

Qué ocurre desde que el núcleo termina de cargarse hasta que la máquina ofrece servicios: el proceso número uno, los niveles de ejecución del sistema clásico con sus enlaces de arranque y parada, y cómo lo ha sustituido systemd con sus unidades y sus targets.

El proceso número uno

Cuando el núcleo termina de cargarse no hay todavía ningún programa de usuario en marcha. Lo primero que lanza es un único proceso, y de ese proceso descienden todos los demás. Recibe el identificador 1 y su cometido es poner el sistema en el estado de funcionamiento que corresponda: montar los sistemas de ficheros, levantar la red y arrancar los servicios.

El ejecutable clásico era /sbin/init. En cualquier distribución actual esa ruta sigue existiendo, pero es un enlace simbólico al ejecutable de systemd, que vive en /lib/systemd/systemd o en /usr/lib/systemd/systemd. Es un detalle que confunde: ver /sbin/init no significa que la máquina use el sistema de inicio antiguo.

El proceso número uno tiene además una responsabilidad que se pregunta: adopta a los procesos que se quedan huérfanos. Cuando un proceso termina antes que sus hijos, esos hijos pasan a colgar del proceso 1, que es quien recoge su código de salida y evita que queden bloqueados en el sistema.

bash
ps -p 1 -o pid,comm      # qué programa es el proceso 1 en esta máquina
ls -l /sbin/init         # a dónde apunta realmente

El proceso 1 es el antepasado de todos los demás y el que adopta a los huérfanos. Si muere, el sistema no puede seguir: no hay a quién colgar los procesos.

Para el examen

  • PID 1: el antepasado de todos los procesos

  • Su papel especial: adopta a los procesos huérfanos

  • Si muere: el sistema no puede seguir

Los niveles de ejecución del sistema clásico

El sistema de inicio clásico define el estado de la máquina con un número, el nivel de ejecución o runlevel. Cambiar de nivel significa arrancar unos servicios y parar otros, y hay dos niveles que no son estados de trabajo sino transiciones: apagar y reiniciar.

NivelEstado de la máquina
0Apagado. Se para todo y se corta la alimentación
1Monousuario: solo root, sin red ni servicios. Para reparar
2Multiusuario
3Multiusuario, típicamente con red y sin entorno gráfico
4Libre, sin uso asignado por la distribución
5Multiusuario con entorno gráfico
6Reinicio

El nivel monousuario es la herramienta de rescate por excelencia: arranca con lo mínimo, sin red y sin servicios, para poder reparar un sistema que no llega a levantar del todo o para cambiar una contraseña olvidada de administrador.

Cuidado con el nivel por defecto, que es un dato que se pregunta mal a menudo. No es universal: depende de la distribución. En la familia Debian el valor tradicional es el 2; en la familia Red Hat clásica es el 3 sin entorno gráfico y el 5 con él. Responder un número como si valiera para todas es un error.

0 apaga y 6 reinicia. Confundirlos es el fallo típico, y en un examen basta recordar que el 0 es el final de la escala hacia abajo.

Para el examen

  • Nivel 0: apagar

  • Nivel 1: monousuario

  • Nivel 6: reiniciar

  • Fallo típico: confundir el 0 con el 6

Los guiones de servicio y los directorios rc

En el sistema clásico, cada servicio se gobierna con un guion de shell guardado en /etc/init.d. Ese guion sabe arrancar, parar y consultar el estado de su servicio, y es lo que hay detrás del comando service de toda la vida.

Lo que decide qué guiones se ejecutan en cada nivel no está dentro del guion, sino fuera: hay un directorio por nivel, de /etc/rc0.d a /etc/rc6.d, más /etc/rcS.d para la fase inicial. Dentro de cada directorio no hay copias de los guiones, sino enlaces simbólicos a los de /etc/init.d.

El nombre del enlace lleva toda la información en dos piezas. La primera letra dice qué hacer al entrar en ese nivel, y el número que va detrás fija el orden, de menor a mayor. Así se resuelve el problema de las dependencias sin ningún mecanismo adicional: si la base de datos tiene que estar lista antes que el servidor de aplicaciones, se le da un número más bajo.

Pieza del nombreSignificado
Letra S inicialIniciar el servicio al entrar en este nivel
Letra K inicialParar (kill) el servicio al entrar en este nivel
Número de dos cifrasOrden de ejecución: primero los más bajos
Resto del nombreEl servicio, que es el destino del enlace en /etc/init.d
bash
# un directorio de nivel es una lista ordenada de enlaces
/etc/rc3.d/S10postgresql  ->  /etc/init.d/postgresql
/etc/rc3.d/S20apache2     ->  /etc/init.d/apache2
/etc/rc3.d/K10tomcat      ->  /etc/init.d/tomcat

S arranca, K para, y el número ordena. En ese ejemplo la base de datos sube antes que el servidor web porque lleva el 10 y no el 20.

Para el examen

  • Prefijo S: arranca el servicio

  • Prefijo K: lo para

  • El número que sigue: fija el orden

systemd y los targets

systemd sustituyó al sistema clásico en prácticamente todas las distribuciones. El cambio de fondo es que ya no ejecuta guiones en cadena, sino que conoce las dependencias entre servicios y puede arrancar en paralelo todo lo que no dependa de nada, lo que acorta mucho el arranque.

El primer cambio visible es de vocabulario: los estados ya no se llaman runlevels ni se identifican por un número, sino targets identificados por un nombre. La equivalencia no es exacta pero se pregunta tal cual.

Nivel clásicoTarget de systemd
0poweroff.target
1rescue.target
2, 3 y 4multi-user.target
5graphical.target
6reboot.target

Un target no es un número de estado, es un punto de sincronización: un conjunto de unidades que tienen que estar levantadas para considerar alcanzado ese estado. Por eso varios niveles antiguos caen en el mismo target, y por eso un sistema puede tener targets propios que no corresponden a ningún runlevel.

bash
systemctl get-default                  # a qué target arranca la máquina
systemctl set-default multi-user.target
systemctl isolate rescue.target        # cambiar de estado ahora mismo
systemctl list-units --type=target

Los targets van por nombre y no por número, y no hay correspondencia uno a uno: los niveles 2, 3 y 4 desembocan todos en multi-user.target.

Para el examen

  • Cómo se identifican: por nombre, no por número

  • Correspondencia con los runlevels: no es uno a uno

  • Niveles 2, 3 y 4: desembocan todos en multi-user.target

Las unidades de systemd

La pieza básica de systemd no es el servicio sino la unidad, un fichero de configuración que describe algo que el sistema puede gestionar. La extensión dice de qué tipo es, y esa lista es lo primero que hay que saber para entender cualquier salida de systemctl.

ExtensiónQué describe
.serviceUn servicio o demonio
.targetUn conjunto de unidades: un punto de sincronización
.socketUn puerto o socket que, al recibir tráfico, arranca su servicio
.timerUna ejecución programada, la alternativa de systemd a cron
.mountUn punto de montaje
.deviceUn dispositivo reconocido por el sistema

Las unidades que trae la distribución viven en /lib/systemd/system y no se tocan. Las propias, y las modificaciones locales de las anteriores, van en /etc/systemd/system, que tiene prioridad. Esa separación es lo que permite que una actualización del paquete no borre los cambios del administrador.

Al editar o añadir una unidad, systemd no se entera solo: hay que pedirle que relea la configuración. Olvidarlo es la causa más frecuente de que un cambio no surta efecto.

bash
systemctl daemon-reload            # releer las unidades tras editarlas
systemctl list-units --type=service --state=running
systemctl mask apache2             # impedir que se arranque, ni a mano
systemctl unmask apache2
systemctl list-unit-files          # qué hay instalado y si está habilitado

Hay tres verbos que se parecen y no son lo mismo. stop para el servicio ahora. disable evita que arranque en el próximo inicio, pero deja arrancarlo a mano. mask va más lejos: enmascara la unidad, de forma que ni siquiera un intento manual la levanta, y es lo que se usa cuando un servicio no debe correr bajo ningún concepto.

stop actúa ahora, disable actúa en el siguiente arranque y mask bloquea la unidad por completo. Si un servicio se niega a arrancar sin dar error claro, lo primero es mirar si está enmascarado.

Para el examen

  • stop: actúa ahora

  • disable: actúa en el siguiente arranque

  • mask: bloquea la unidad por completo

  • Diagnóstico: si un servicio no arranca sin error claro, mirar si está enmascarado