Cambiar niveles de ejecución y reiniciar el sistema

TEMARIO

Introducción

En los sistemas operativos que siguen los principios de diseño de Unix, como Linux, una característica común es el uso de procesos separados conocidos como «daemons» o servicios para controlar diversas funciones del sistema. Los daemons son responsables de una amplia gama de características extendidas del sistema operativo, incluyendo servicios de aplicaciones de red (como servidores HTTP, intercambio de archivos y correo electrónico), bases de datos, configuración bajo demanda, entre otros.

Aunque Linux utiliza un núcleo monolítico, los daemons juegan un papel crucial en muchos aspectos de bajo nivel del sistema operativo. Por ejemplo, se encargan del equilibrio de carga y la configuración del firewall, mostrando así su importancia en la gestión y el funcionamiento eficiente del sistema.

Los «daemons» (o demonios) activos en un sistema dependen de su propósito específico. Es importante que se pueda modificar la lista de daemons activos mientras el sistema está en funcionamiento, de modo que los servicios puedan iniciarse o detenerse sin necesidad de reiniciar todo el sistema. Para resolver este problema, cada distribución principal de Linux proporciona alguna herramienta o utilidad de administración de servicios para controlar el sistema.

Existen dos métodos principales para controlar servicios en sistemas Linux: mediante scripts de shell o a través de programas y sus archivos de configuración correspondientes. El enfoque de scripts de shell es típicamente asociado con el estándar SysVinit, también llamado System V o simplemente SysV. Por otro lado, el método basado en programas y archivos de configuración es utilizado por systemd y Upstart.

Anteriormente, los administradores de servicios basados en SysV fueron los más comunes en las distribuciones de Linux, pero hoy en día, los basados en sistemas como systemd son más frecuentes en la mayoría de las distribuciones. El administrador de servicios es el primer programa lanzado por el núcleo durante el proceso de arranque, por lo que siempre tiene un PID (número de identificación del proceso) de 1.

Estándar SysVinit

Un administrador de servicios basado en el estándar SysVinit proporcionará conjuntos predefinidos de estados del sistema, llamados runlevels, y sus correspondientes archivos de script de servicio para ser ejecutados. Los niveles de ejecución están numerados de 0 a 6, y
generalmente se asignan a los siguientes propósitos:

Runlevel 0.- Apagado del sistema.
Runlevel 1, s o usuario único.- Modo de usuario único, sin red y otras capacidades no esenciales (modo de mantenimiento).
Runlevel 2, 3 o 4.- Modo multiusuario. Los usuarios pueden iniciar sesión por consola o red. Los niveles de ejecución 2 y 4 no se usan con frecuencia.
Runlevel 5.- Modo multiusuario. Es equivalente a 3, más el inicio de sesión en modo gráfico.
Runlevel 6.- Reinicio del sistema.

El programa principal encargado de gestionar los niveles de ejecución y los procesos/demonios relacionados en sistemas Linux es /sbin/init. Durante el inicio del sistema, init determina el nivel de ejecución requerido, el cual puede ser especificado por un parámetro del sistema operativo o en el archivo /etc/inittab, y carga los scripts correspondientes asociados a ese nivel de ejecución. Cada nivel de ejecución puede tener múltiples scripts de servicio, comúnmente ubicados en el directorio /etc/init.d/. Es importante destacar que los niveles de ejecución pueden variar entre diferentes distribuciones de Linux, por lo que algunas distribuciones basadas en SysV proporcionan descripciones breves sobre el propósito de cada nivel de ejecución. La sintaxis del archivo /etc/inittab usa este formato:

El id es un nombre genérico de hasta cuatro caracteres de longitud utilizado para identificar la entrada. La entrada runlevels es una lista de números de niveles para los que se debe ejecutar una acción específica. El término action define cómo init ejecutará el proceso indicado por el término process. Las acciones disponibles son:

boot.- El proceso se ejecutará durante la inicialización del sistema. El campo runlevels se ignora.
bootwait.- El proceso se ejecutará durante la inicialización del sistema e init esperará hasta que termine para continuar. El campo runlevels se ignora.
sysinit.- El proceso se ejecutará después de la inicialización del sistema, independientemente del nivel de ejecución. El campo runlevels se ignora.
wait.- El proceso se ejecutará para los niveles de ejecución dados e init esperará hasta que termine para continuar.
respawn.- El proceso se reiniciará si finaliza.
ctrlaltdel.- El proceso se ejecutará cuando el proceso init reciba la señal SIGINT, que se activará cuando se presione la secuencia de teclas Ctrl + Alt + Supr .

El nivel de ejecución por defecto, cuando no se especifica otro parámetro del núcleo, se define en /etc/inittab bajo la entrada id:x:initdefault. Aquí, la «x» representa el número del nivel de ejecución predeterminado. Sin embargo, este número no debe ser ni 0 ni 6, ya que podrían provocar un apagado o reinicio inmediato del sistema al finalizar el proceso de arranque. A continuación, se muestra un ejemplo típico del archivo /etc/inittab:

El comando telinit q debe ejecutarse cada vez que se modifica el archivo /etc/inittab. El argumento q (o Q) le dice a init que vuelva a cargar su configuración. Este paso es importante para evitar que el sistema se detenga debido a una configuración incorrecta en /etc/inittab.

Los scripts utilizados por init para configurar cada nivel de ejecución se almacenan en
/etc/init.d/. Cada nivel de ejecución tiene su propio directorio en /etc/ (por ejemplo, /etc/rc0.d/, /etc/rc1.d/, /etc/rc2.d/, etc.) con enlaces simbólicos a los scripts que deben ejecutarse al iniciar el nivel correspondiente. Estos enlaces simbólicos indican si un servicio debe iniciarse o terminarse al entrar en un nivel de ejecución específico. Los enlaces que comienzan con «K» indican que el servicio debe detenerse (kill), mientras que los que comienzan con «S» indican que el servicio debe iniciarse (start). Por ejemplo, en el directorio
/etc/rc1.d/ se encuentran enlaces a scripts de red que comienzan con «K«, ya que el nivel de ejecución 1 generalmente no tiene conectividad de red.

El comando runlevel muestra el nivel de ejecución actual para el sistema. El comando runlevel muestra dos valores, el primero es el nivel de ejecución anterior y el segundo es el nivel de ejecución actual:

La letra N en la salida muestra que el nivel de ejecución no ha cambiado desde el último arranque. En el ejemplo, el runlevel 5 es el nivel de ejecución actual del sistema.

El mismo programa init puede usarse para alternar entre niveles de ejecución en un sistema en ejecución, sin la necesidad de reiniciar. El comando telinit también se puede usar para alternar entre los niveles de ejecución. Por ejemplo, los comandos telinit 1, telinit s o telinit S cambiarán el sistema al nivel de ejecución 1.

systemd

Actualmente, systemd es el conjunto de herramientas más utilizado para administrar los recursos y servicios del sistema, que systemd denomina unidades (units). Una unidad consta de nombre, tipo y un archivo de configuración correspondiente. Por ejemplo, la unidad para un proceso de servidor httpd (como el servidor web Apache) será httpd.service en distribuciones basadas en Red Hat, su archivo de configuración también se llamará httpd.service (en distribuciones basadas en Debian esta unidad es llamada apache2.service). Hay siete tipos distintos de unidades systemd:

service.- El tipo de unidad más común, para recursos activos del sistema que se pueden iniciar, interrumpir y recargar.
socket.- El tipo de unidad de socket puede ser un socket de sistema de archivos o un socket de red. Todas las unidades de socket tienen una unidad de servicio correspondiente, cargada cuando el socket recibe una solicitud.
device.- Una unidad de dispositivo está asociada con un dispositivo de hardware identificado por el núcleo. Un dispositivo solo se tomará como una unidad systemd si existe una regla udev para este propósito. Se puede usar una unidad de dispositivo para resolver dependencias de configuración cuando se detecta cierto hardware, dado que las propiedades de la regla udev se pueden usar como parámetros para la unidad de dispositivo.
mount.- Una unidad de montaje es una definición de punto de montaje en el sistema de archivos, similar a una entrada en /etc/fstab.
automount.- Una unidad de montaje automático también es una definición de punto de montaje en el sistema de archivos, pero se monta automáticamente. Cada unidad de montaje automático tiene una unidad de montaje correspondiente, que se inicia cuando se accede al punto de montaje automático.
target.- Una unidad target es una agrupación de otras unidades, administradas como una sola unidad.
snapshot.- Una unidad snapshot es un estado guardado del administrador del sistema (no disponible en todas las distribuciones de Linux).

El comando principal para controlar las unidades systemd es systemctl. El comando systemctl se usa para ejecutar todas las tareas relacionadas con la activación, desactivación, ejecución, interrupción, monitoreo de la unidad, etc. Para una unidad ficticia llamada unit.service, por ejemplo, las acciones más comunes de systemctl serán:

systemctl start unit.service.- Inicia una unidad (unit).
systemctl stop unit.service.- Detiene una unidad (unit).
systemctl restart unit.service.- Reinicia una unidad (unit).
systemctl status unit.service.- Muestra el estado de la unidad (unit), incluyendo si está en ejecución o no.
systemctl is-active unit.service.- Muestra active Si la unidad (unit) está en ejecución o inactiva.
systemctl enable unit.service.- La unidad (unit) se cargará durante la inicialización del sistema.
systemctl disable unit.service.- La unidad (unit) no se cargará durante la inicialización del sistema.
systemctl is-enabled unit.service.- Verifica si la unidad (unit) comienza con el sistema. La respuesta se almacena en la variable $?. El valor 0 indica que unit comienza con el sistema y el valor 1 indica que unit no comienza con el sistema.

Las instalaciones más recientes de systemd en realidad enumerarán la configuración de una unidad para el tiempo de arranque. Por ejemplo:

Si no existen otras unidades con el mismo nombre en el sistema, el sufijo después del punto se puede quitar. Si, por ejemplo, solo hay una unidad httpd de tipo service, entonces solo httpd es suficiente como parámetro de unidad para systemctl.

El comando systemctl también puede controlar system targets. La unidad multi-user.target, por ejemplo, combina todas las unidades requeridas por el entorno del sistema multiusuario. Es similar al nivel de ejecución número 3 en un sistema que utiliza SysV.

El comando systemctl isolate alterna entre diferentes objetivos. Por lo tanto, para alternar
manualmente al objetivo multiusuario:

Los sistemas basados en systemd, como muchas distribuciones de Linux modernas, utilizan objetivos específicos en lugar de los niveles de ejecución tradicionales de SysV, desde runlevel0.target hasta runlevel6.target. A diferencia de SysV, systemd no emplea el archivo /etc/inittab para gestionar estos niveles.

Para cambiar el objetivo predeterminado del sistema en systemd, se utiliza la opción systemd.unit, que se agrega a la lista de parámetros del núcleo del sistema operativo. Por ejemplo, para establecer multi-user.target como el objetivo estándar, se añadiría el parámetro del núcleo systemd.unit=multi-user.target.

Es relevante mencionar que todos los parámetros del núcleo pueden hacerse persistentes al modificar la configuración del gestor de arranque del sistema, permitiendo que los cambios en los objetivos de systemd u otros parámetros se conserven entre reinicios del sistema.

Otra forma de cambiar el objetivo predeterminado es modificar el enlace simbólico
/etc/systemd/system/default.target para que apunte al objetivo deseado. La redefinición del enlace se puede hacer con el comando systemctl por sí mismo:

Del mismo modo, puede determinar cuál es el objetivo de arranque predeterminado de su sistema con el siguiente comando:

Similar a los sistemas que adoptan SysV, el objetivo predeterminado nunca debe apuntar a shutdown.target, ya que corresponde al nivel de ejecución 0 (apagado).

Los archivos de configuración asociados con cada unidad se pueden encontrar en el directorio /lib/systemd/system/. El comando systemctl list-unit-files enumera todas las unidades disponibles y muestra si están habilitadas para iniciarse cuando se inicia el sistema. La opción –type seleccionará solo las unidades para un tipo dado, como en systemctl list-unit-files –type=service y systemctl list-unit-files –type=target.

Las unidades activas o unidades que han estado activas durante la sesión actual del sistema se pueden enumerar con el comando systemctl list-units. Al igual que la opción list-unit-files, el comando systemctl list-units –type=service seleccionará solo unidades de tipo service y el comando systemctl list-units –type=target seleccionará solo unidades de tipo target.

systemd también es responsable de desencadenar y responder a eventos relacionados con la energía del sistema. El comando systemctl suspend pondrá el sistema en modo de bajo consumo, manteniendo los datos actuales en la memoria. El comando systemctl hibernate copiará todos los datos de la memoria al disco, por lo que el estado actual del sistema se puede recuperar después de apagarlo. Las acciones asociadas con tales eventos se definen en el archivo /etc/systemd/logind.conf o en archivos separados dentro del directorio /etc/systemd/logind.conf.d/. Sin embargo, esta función systemd solo se puede usar cuando no hay otro administrador de energía ejecutándose en el sistema, como el demonio acpid. El demonio acpid es el principal administrador de energía para Linux y permite ajustes más precisos a las acciones posteriores a eventos relacionados con la energía, como cerrar la tapa del portátil, batería baja o niveles de carga de la batería.

Upstart

Los archivos de inicio que usa Upstart están guardados en la carpeta /etc/init/. Puedes ver una lista de los servicios del sistema usando el comando initctl list. Este comando también te muestra el estado actual de los servicios y, si está disponible, su número de identificación de proceso (PID).

A partir de la versión de Ubuntu 21.10, es probable que tu sistema utilice systemd en lugar de Upstart para administrar los servicios del sistema.

Este ejemplo refleja (línea coloreada) un problema que impidió que el servicio se ejecutara correctamente, lo que puede deberse a errores en la configuración, problemas de dependencias o fallos durante la ejecución del propio servicio.

Cada acción de Upstart tiene su propio comando independiente. Por ejemplo, el comando start puede usarse para iniciar la sexta terminal virtual:

El estado actual de un recurso se puede verificar con el comando status:

Y la interrupción de un servicio se realiza con el comando stop:

Upstart no usa el archivo /etc/inittab para definir los niveles de ejecución, pero los comandos heredados runlevel y telinit todavía pueden usarse para verificar y alternar entre los niveles de ejecución.

Apagado y Reinicio

El comando shutdown es esencial para apagar o reiniciar un sistema, especialmente en entornos multiusuario. Al ejecutarlo, notifica a los usuarios conectados sobre el apagado o reinicio inminente, evitando nuevos inicios de sesión para una transición sin interrupciones. Esto asegura que no se pierdan tareas o procesos durante el proceso de apagado o reinicio.

Es importante destacar que el comando shutdown actúa como intermediario entre el usuario y el administrador de servicios del sistema, ya sea SysV o systemd, dependiendo de la configuración del sistema. Esto significa que, al ejecutar shutdown, en realidad estás solicitando al administrador de servicios que realice la acción de apagar o reiniciar el sistema.

Solo se requiere el parámetro time. El parámetro time define cuándo se ejecutará la acción solicitada, aceptando los siguientes formatos:

hh:mm.- Este formato especifica el tiempo de ejecución como hora y minutos.
+m.- Este formato especifica cuántos minutos esperar antes de la ejecución.
now o +0.- Este formato determina la ejecución inmediata.

El parámetro message es el texto de advertencia enviado a todas las sesiones de terminal de los usuarios conectados.

En sistemas que utilizan SysV, se puede restringir quién puede reiniciar la máquina al presionar Ctrl + Alt + Supr. Esto se logra mediante la opción -a en el comando shutdown en la línea relacionada con ctrlaltdel del archivo /etc/inittab. Con esta configuración, solo los usuarios listados en /etc/shutdown.allow tendrán permiso para reiniciar el sistema con esta combinación de teclas..

En sistemas que utilizan systemd, el comando systemctl se puede utilizar para apagar o reiniciar la máquina. Para reiniciar el sistema, se emplea systemctl reboot, y para apagarlo, se utiliza systemctl poweroff. Estos comandos necesitan privilegios de root para ejecutarse, ya que los usuarios comunes no pueden realizar estas acciones.

No todas las tareas de mantenimiento necesitan un reinicio o apagado del sistema. No obstante, al cambiar al modo de usuario único, es crucial advertir a los usuarios con sesiones activas para evitar interrupciones abruptas en sus actividades.

De manera similar a lo que hace el comando shutdown cuando se apaga o reinicia el sistema, el comando wall puede enviar un mensaje a las sesiones de terminal de todos los usuarios conectados. Para hacerlo, el administrador del sistema solo necesita proporcionar un archivo o escribir directamente el mensaje como parámetro para ordenar wall.