9.1. Arranque del sistema
Cuando inicia el equipo, muchos mensajes que aparecen en la pantalla muestran varias inicializaciones y configuraciones automáticas que se están ejecutando. Algunas veces deseará alterar ligeramente cómo funciona esta etapa, lo que significa que necesitará entenderlas bien. Éste es el propósito de esta sección.
En sistemas con una BIOS, primero, la BIOS toma el control del ordenador, inicializa los controladores y hardware, detecta los discos y puentea todos juntos. Después busca el Master Boot Record (MBR) del primer disco en el orden de arranque y carga el código almacenado allí (primera etapa). Este código lanza el segundo paso y finalmente ejecuta el cargador de arranque.
En contraste con la BIOS, la UEFI es más sofisticada, conoce los sistemas de archivos y puede leer las tablas de partición. La interfaz busca en el almacenamiento del sistema para una partición etiquetada con un identificador globalmente único específico (
GUID esa la marca como
Partición del sistema EFI ()
ESP), donde se ubican los cargadores de arranque, los gestores de arranque, el shell UEFI, etc., y lanza el cargador de arranque deseado. Si está habilitado Secure Boot, el proceso de arranque verificará la autenticidad de los binarios de EFI por firma (por eso se requiere
Grub-efi-arch- signed en este caso). La especificación de la UEFI también define soporte para el arranque en el modo BIOS heredado. Esto se llama el
Compatibility Support Module (
CSM). Si el CSM está habilitado, intentará arrancar del MBR de una unidad. Sin embargo, muchos sistemas nuevos no soportan ya el modo CSM.
En ambos casos, el gestor de arranque actual toma el control, encuentra un gestor de arranque unido o el núcleo en el disco, lo carga y lo ejecuta. El kernel se inicializa entonces, y comienza a buscar y montar la partición que contiene el sistema de archivos raíz, y finalmente ejecuta el primer programa - init
. A menudo, esta "partición raíz" y este init
se encuentran, de hecho, en un sistema de archivos virtual que sólo existe en la RAM (de ahí su nombre, "initramfs", antes llamado "initrd" por "disco RAM de inicialización"). Este sistema de archivos lo carga en memoria el gestor de arranque, a menudo desde un archivo en un disco duro o desde la red. Contiene el mínimo requerido por el kernel para cargar el "verdadero" sistema de archivos raíz: pueden ser módulos de controladores para el disco duro u otros dispositivos sin los cuales el sistema no puede arrancar, o, más frecuentemente, scripts de inicialización y módulos para montar matrices RAID, abrir particiones cifradas, activar volúmenes LVM, etc. Una vez montada la partición raíz, initramfs cede el control al init real, y la máquina vuelve al proceso de arranque estándar.
9.1.1. El sistema de inicio systemd
Actualmente systemd proporciona el «init real» y esta sección documenta este sistema de inicio.
Systemd ejecuta varios procesos que se encargan de configurar el sistema: teclado, controladores, sistemas de archivos, redes, servicios. Hace esto a la vez que mantiene una visión global del sistema como un todo y de los requerimientos de los componentes. Cada componente se describe en un fichero unidad o "unit file" (a veces más de uno). La sintaxis de los mismos se deriva de la de los muy extendidos archivos ".ini". Es decir que utiliza pares clave = valor
agrupados entre cabeceras de [sección]
. Los archivos unit se guardan en /lib/systemd/system/
y /etc/systemd/system/
. Aunque hay varios tipos, aquí nos vamos a concentrar en los servicios ("services") y metas ("targets").
Un archivo de “.service
file” de systemd describe un proceso gestionado por systemd. Contiene más o menos la misma información que los antiguos scripts de inicio, pero expresada en de forma declarativa (y mucho más concisa). Systemd se ocupa de la mayoría de las tareas repetitivas (arrancar y parar el proceso, comprobar su estado, registrar los errores, soltar privilegios, etc) y el archivo de servico únicamente tiene que proporcionar los parámetros especificos de cada servicio. Por ejemplo aquí se muestra el fichero de servicio para SSH:
[Unit]
Description=OpenBSD Secure Shell server
Documentation=man:sshd(8) man:sshd_config(5)
After=network.target auditd.service
ConditionPathExists=!/etc/ssh/sshd_not_to_be_run
[Service]
EnvironmentFile=-/etc/default/ssh
ExecStartPre=/usr/sbin/sshd -t
ExecStart=/usr/sbin/sshd -D $SSHD_OPTS
ExecReload=/usr/sbin/sshd -t
ExecReload=/bin/kill -HUP $MAINPID
KillMode=process
Restart=on-failure
RestartPreventExitStatus=255
Type=notify
RuntimeDirectory=sshd
RuntimeDirectoryMode=0755
[Install]
WantedBy=multi-user.target
Alias=sshd.service
La sección [Unit]
contiene información genérica sobre el servicio, como su descripción y recursos de página manual, así como relaciones (dependencia y orden) a otros servicios. La parte [Servicio]
contiene las declaraciones relacionadas con la ejecución del servicio (comenzar, detener, matar, reiniciar), directorios y ficheros de configuración utilizados. La última sección, [Install]
, de nuevo lleva información genérica en la que los objetivos para instalar el servicio y, en este caso, el alias que se puede utilizar en lugar del nombre del servicio. Como se puede ver, hay muy poco código allí, sólo declaraciones. Systemd se ocupa de mostrar los informes de progreso, mantener el seguimiento de los procesos e incluso reiniciarlos cuando sea necesario. La sintaxis de estos archivos ea descrita completamente en varias páginas del manual (por ejemplo. systemd.service(5), systemd.unit(5), systemd.exec(5), etc.).
Un “fichero .target
” describe un estado del sistema en el cual se sabe que está operativo un conjunto de servicios. Se puede hacer una analogía los antiguos niveles de ejecución ("runlevels"). Uno de los objetivos es local-fs.target
; cuando se alcanza, el resto del sistema puede asumir que todos los sistemas de archivos locales están montados y son accesibles. Otros objetivoss incluyen network-online.target
y sound.target
(para una lista completa de objetivos especiales ver sistemad.especial(7)). Las dependencias de un objetivo se pueden establecer directamente en su archivo de configuración o "target file" (en la línea Requires=
) o bien utilizando un enlace simbólico a un archivo de servicio ("service file") en el directorio /lib/systemd/system/targetname.target.wants/
. Por ejemplo /etc/systemd/system/printer.target.wants/
contiene un enlace a /lib/systemd/system/cups.service
; systemd se asegurará de que las CUPS estén en ejecución para poder efectuar printer.target
.
Puesto que los archivos de unidad son declarativos en lugar de scripts o programas, no se pueden ejecutar directamente; tienen que ser interpretados por systemd. Existen varias utilidades que permiten al administrador interactuar con systemd y controlar el estado del sistema y de cada componente.
La primera de estas utilidades es systemctl
. Cuando se ejecuta sin argumentos lista todos los archivos de unidad conocidos por systemd (excepto los que han sido deshabilitados), así como su estado. systemctl status
muestra una visión mejor de los servicios y sus procesos relacionados. Si se proporciona el nombre de un servico (como p.ej. systemctl status ntp.service
) muestra aún más detealles, así como las últimas líneas del registro relacionadas con el servicio (más información más adelante).
Para arrancar un servicio manualmente basta ejecutar systemctl start nombredelservicio.service
. Como se puede suponer, para parar un servicio se hace con systemctl stop nombredelservicio.service
; otros subcomandos disponibles son reload
y restart
.
Para establecer si un servicio está activo (es decir, si se debe arrancar automáticamente al inicio o no) utilce el comando systemctl enable nombredelservicio.service
(o disable
). is-enabled
permite saber si está activo o no.
Una característica interesante de systemd es que incluye un componente de registro llamado journald
. Viene como complemento a los sistemas de registro tradicionales como syslogd
, pero añade características interesantes como un enlace formal entre un servicio y los mensajes que genera, así como la posibilidad de capturar los mensajes de error generados por su secuencia de inicialización. Los mensajes se pueden mostrar con la ayuda del comando journalctl
. Sin argumentos símplemente vuelca todos los mensajes que han ocurrido desde el arranque del sistema, aunque no se suele utilizar de esa forma. Normalmente se utiliza con un identificador de servicio:
#
journalctl -u ssh.service
May 20 19:28:59 debian systemd[1]: Starting ssh.service - OpenBSD Secure Shell server...
May 20 19:28:59 debian sshd[532]: Server listening on 0.0.0.0 port 22.
May 20 19:28:59 debian sshd[532]: Server listening on :: port 22.
May 20 19:28:59 debian systemd[1]: Started ssh.service - OpenBSD Secure Shell server.
May 20 19:34:17 debian sshd[532]: Received signal 15; terminating.
May 20 19:34:17 debian systemd[1]: Stopping ssh.service - OpenBSD Secure Shell server...
May 20 19:34:17 debian systemd[1]: ssh.service: Deactivated successfully.
May 20 19:34:17 debian systemd[1]: Stopped ssh.service - OpenBSD Secure Shell server.
-- Boot 539ead7492344c2baddeea6bba357eee --
May 20 19:36:56 debian systemd[1]: Starting ssh.service - OpenBSD Secure Shell server...
May 20 19:36:56 debian sshd[532]: Server listening on 0.0.0.0 port 22.
May 20 19:36:56 debian sshd[532]: Server listening on :: port 22.
May 20 19:36:56 debian systemd[1]: Started ssh.service - OpenBSD Secure Shell server.
Otra opción útil es -f
, que hace que journalctl
siga mostrando los nuevos mensajes a medida que se van emitiendo (semejante a lo que ocurre con tail -f file
).
Si un servicio parece que no está funcionando como debiera, el primer paso para resolver el problema es comprobar si el servicio está ejecutándose realmente mediante systemctl status
. Si no es así y los mensajes que se muestran no son suficientes para diagnosticar el problema se pueden comprobar los registros que ha recogido journald relacionados con es servicio. Por ejemplo, suponiendo que el servidor SSH no funciona:
#
systemctl status ssh.service
● ssh.service - OpenBSD Secure Shell server
Loaded: loaded (/lib/systemd/system/ssh.service; enabled)
Active: failed (Result: start-limit) since Tue 2015-03-31 17:30:36 CEST; 1s ago
Process: 1023 ExecReload=/bin/kill -HUP $MAINPID (code=exited, status=0/SUCCESS)
Process: 1188 ExecStart=/usr/sbin/sshd -D $SSHD_OPTS (code=exited, status=255)
Main PID: 1188 (code=exited, status=255)
Mar 31 17:30:36 mirtuel systemd[1]: ssh.service: main process exited, code=exited, status=255/n/a
Mar 31 17:30:36 mirtuel systemd[1]: Unit ssh.service entered failed state.
Mar 31 17:30:36 mirtuel systemd[1]: ssh.service start request repeated too quickly, refusing to start.
Mar 31 17:30:36 mirtuel systemd[1]: Failed to start OpenBSD Secure Shell server.
Mar 31 17:30:36 mirtuel systemd[1]: Unit ssh.service entered failed state.
#
journalctl -u ssh.service
-- Logs begin at Tue 2015-03-31 17:29:27 CEST, end at Tue 2015-03-31 17:30:36 CEST. --
Mar 31 17:29:27 mirtuel sshd[424]: Server listening on 0.0.0.0 port 22.
Mar 31 17:29:27 mirtuel sshd[424]: Server listening on :: port 22.
Mar 31 17:29:29 mirtuel sshd[424]: Received SIGHUP; restarting.
Mar 31 17:29:29 mirtuel sshd[424]: Server listening on 0.0.0.0 port 22.
Mar 31 17:29:29 mirtuel sshd[424]: Server listening on :: port 22.
Mar 31 17:30:10 mirtuel sshd[1147]: Accepted password for roland from 192.168.1.129 port 38742 ssh2
Mar 31 17:30:10 mirtuel sshd[1147]: pam_unix(sshd:session): session opened for user roland by (uid=0)
Mar 31 17:30:35 mirtuel sshd[1180]: /etc/ssh/sshd_config line 28: unsupported option "yess".
Mar 31 17:30:35 mirtuel systemd[1]: ssh.service: main process exited, code=exited, status=255/n/a
Mar 31 17:30:35 mirtuel systemd[1]: Unit ssh.service entered failed state.
Mar 31 17:30:35 mirtuel sshd[1182]: /etc/ssh/sshd_config line 28: unsupported option "yess".
Mar 31 17:30:35 mirtuel systemd[1]: ssh.service: main process exited, code=exited, status=255/n/a
Mar 31 17:30:35 mirtuel systemd[1]: Unit ssh.service entered failed state.
Mar 31 17:30:35 mirtuel sshd[1184]: /etc/ssh/sshd_config line 28: unsupported option "yess".
Mar 31 17:30:35 mirtuel systemd[1]: ssh.service: main process exited, code=exited, status=255/n/a
Mar 31 17:30:35 mirtuel systemd[1]: Unit ssh.service entered failed state.
Mar 31 17:30:36 mirtuel sshd[1186]: /etc/ssh/sshd_config line 28: unsupported option "yess".
Mar 31 17:30:36 mirtuel systemd[1]: ssh.service: main process exited, code=exited, status=255/n/a
Mar 31 17:30:36 mirtuel systemd[1]: Unit ssh.service entered failed state.
Mar 31 17:30:36 mirtuel sshd[1188]: /etc/ssh/sshd_config line 28: unsupported option "yess".
Mar 31 17:30:36 mirtuel systemd[1]: ssh.service: main process exited, code=exited, status=255/n/a
Mar 31 17:30:36 mirtuel systemd[1]: Unit ssh.service entered failed state.
Mar 31 17:30:36 mirtuel systemd[1]: ssh.service start request repeated too quickly, refusing to start.
Mar 31 17:30:36 mirtuel systemd[1]: Failed to start OpenBSD Secure Shell server.
Mar 31 17:30:36 mirtuel systemd[1]: Unit ssh.service entered failed state.
#
vi /etc/ssh/sshd_config
#
systemctl start ssh.service
#
systemctl status ssh.service
● ssh.service - OpenBSD Secure Shell server
Loaded: loaded (/lib/systemd/system/ssh.service; enabled)
Active: active (running) since Tue 2015-03-31 17:31:09 CEST; 2s ago
Process: 1023 ExecReload=/bin/kill -HUP $MAINPID (code=exited, status=0/SUCCESS)
Main PID: 1222 (sshd)
CGroup: /system.slice/ssh.service
└─1222 /usr/sbin/sshd -D
#
Después de comprobar el estado del servicio (fallido) comprobamos los registros; indican un error en el archivo de configuración. Después de editar el archivo de configuración y corregir el error reiniciamos el servicio y comprobamos que efectivamente está funcionando.
9.1.2. El sistema de inicio System V
El sistema de incio System V (al cual llamaremos init por brevedad) ejecuta varios procesos siguiendo instrucciones del archivo /etc/inittab
. El primer programa que ejecuta (que se corresponde con el paso sysinit) es /etc/init.d/rcS
, un script que ejecuta todos los programas del directorio /etc/rcS.d/
.
Entre estos encontrará sucesivamente programas a cargo de:
configurar el teclado de la consola;
cargar controladores: el núcleo carga por sí mismo la mayoría de los módulos a medida que el hardware es detectado; los controladores extras se cargan automáticamente cuando los módulos correspondientes son listados en /etc/modules
;
verificar la integridad de los sistemas de archivos;
montar particiones locales;
configurar la red;
montar sistemas de archivos de red (NFS).
Despues de esta etapa, init
toma el control e inicia los programas activados en el nivel de ejecución («runlevel») predeterminado (generalmente el nivel 2). Ejecuta /etc/init.d/rc 2
, un script que inicia todos los servicios enumerados en /etc/rc2.d/
y aquellos cuyos nombres comiencen con la letra «S». Los números de dos cifras que le sigue fueron utilizados históricamente para definir el orden en el que se iniciarán los servicios, pero actualmente el sistema de inicio predeterminado utiliza insserv
, que programa todo automáticamente basándose en las dependencias de los scripts. Cada script de inicio, por lo tanto, declara las condiciones a cumplir para iniciar o detener el servicio (por ejemplo, si debe iniciar antes o después de otro servicio); init
luego los ejecuta en un orden que satisfaga estas condiciones. El enumerado estático de los scripts ya no se tiene en cuenta (pero sus nombres siempre deben comenzar con «S» seguidos de dos números y el nombre real del script utilizado para dependencias). Generalmente, se inician primero los servicios de base (como los registros con rsyslogd
o la asociación de puertos con portmap
) seguidos de los servicios estándar y la interfaz gráfica (gdm
).
Este sistema de inicio basado en dependencias hace posible renumerar automáticamente los scripts, lo que sería tediososo de hacer manualmente y limita el riesgo de error humano ya que se realiza la programación según los parámetros indicados. Otro beneficio es que se pueden iniciar los servicios en paralelo cuando son independientes entre ellos, lo cual puede acelerar el proceso de inicio.
init
distingue varios niveles de ejecución («runlevel») y puede cambiar de uno a otro ejecutando telinit nuevo-nivel
. Inmediatamente, init
ejecuta nuevamente /etc/init.d/rc
con el nuevo nivel de ejecución. Luego, este script ejecutará los servicios faltantes y detendrá aquellos que ya no se desean. Para hacerlo, se refiere al contenido del archivo /etc/rcX.d
(donde X representa el nuevo nivel de ejecución). Los scripts cuyos nombres comienzan con «S» (por «start», iniciar) son los servicios a iniciar; aquellos cuyos nombres comienzan con «K» (por «kill», matar) son los servicios a detener. El script no inicia ningún servicio que ya haya estado activo en el nivel de ejecución anterior.
De forma predeterminada, el inicio System V en Debian utiliza cuatro niveles de ejecución diferentes:
Nivel 0: sólo se lo utiliza temporalmente mientras se apaga el equipo. Como tal, sólo contiene scripts «K».
Nivel 1: también conocido como modo de usuario único, corresponde al sistema en modo degradado; sólo incluye servicios básicos y está destinado a operaciones de mantenimiento donde no se desea la interacción con usuarios normales.
Nivel 2: es el nivel para operaciones normales, lo que incluye servicios de red, una interfaz gráfica, sesiones de usuario, etc.
Nivel 6: similar a nivel 0, excepto a que es utilizada durante la fase de cierre que precede a un reinicio.
Existe otros niveles, especialmente del 3 al 5. De forma predeterminara están configurados para operar de la misma forma que el nivel 2, pero el administrador puede modificarlos (agregando o eliminando scripts en los directorios /etc/rcX.d
correspondientes) para adaptarlos a necesidades particulares.
All the scripts contained in the various /etc/rcX.d
directories are really only symbolic links — created upon package installation by the update-rc.d
program — pointing to the actual scripts which are stored in /etc/init.d/
. The administrator can fine tune the services available in each runlevel by re-running update-rc.d
with adjusted parameters. The update-rc.d(1) manual page describes the syntax in detail. Please note that removing all symbolic links (with the remove
parameter) is not a good method to disable a service. Instead you should simply configure it to not start in the desired runlevel (while preserving the corresponding calls to stop it in the event that the service runs in the previous runlevel). Since update-rc.d
has a somewhat convoluted interface, you may prefer using rcconf
(from the rcconf package) which provides a more user-friendly interface.
Finalmente, init
inicia los programas de control para varias consolas virtuales (getty
). Muestra un prompt esperando por un nombre de usuario y luego ejecuta login usuario
para iniciar una sesión.