Servicios del sistema

A la hora de iniciar el sistema existen unas configuraciones de arranque para los sistemas Linux. Son configuraciones predefinidas por la distribución pero que pueden ser modificadas por el administrador. Estás configuraciones son conocidas como runlevels o niveles de arranque

Un nivel de arranque, por tanto, es la definición de un estado del sistema. Los niveles de arranque se diferencian por un número número (por defecto). Cada nivel de arranque incluye un conjunto de servicios y algunas aplicaciones que se inician o detienen.

Todas las distribuciones proveen la presencia de los niveles de arranque del 0 al 6. Realmente se podrían definir hasta 9 niveles de arranque, pero casi ninguna implementa más de los siete que van del 0 al 6.

En Ubuntu los niveles de arranque siguen el siguiente esquema:

    ➤ 0 — Apagado del sistema. No se apaga, pero ningún proceso queda en ejecución.
    ➤ 1 — Modo monousuario o de mantenimiento. No se puede cambiar de usuario, el sistema 
          arranca con lo básico; un interprete de comandos y algunas utilidades de rescate.
    ➤ 2 — Nivel de arranque por defecto. Arranca un sistema completo multiusuario.
    ➤ 3,4,5 — Igual que en el nivel anterior arrancan un sistema completo multiusuario.
    ➤ 6 — Reinicio; el sistema se apaga y vuelve a iniciarse.

En un sistema en ejecución podemos determinar el nivel de arranque en ejecución con el comando:

$ runlevel 
N 2

El primer caracter, N representa el nivel de arranque anterior. Una N en esta posición indica que el sistema fué iniciado directamente desde el nivel de arranque por defecto, representado por el segundo caracter, en este caso un 2. Si el sistema hubiese estado en un nivel de arranque previo, el primer caracter reflejaría dicho nivel de arranque.

Modificar el nivel de arranque desde la consola implica la ejecución del comando init, o del comando telinit que es un enlace simbólico a init y que se mantiene por compatibilidad.

Para cambiar al nivel de arranque 3 ejecutaríamos:

# init 3

El sistema mostraría mensajes indicando el nivel de arranque que se está dejando y en el que se está entrando.

Para hacer un reinicio mediante cambios de nivel de arranque ejecutaríamos:

# init 6

Ubuntu utiliza los siguientes directorios para gestionar los niveles de arranque:

    Ubuntu
    /etc/
         |--   init.d
         |--   rc0.d
         |--   rc1.d
         |--   rc2.d
         |--   rc3.d
         |--   rc4.d
         |--   rc5.d
         |--   rc6.d
          `--   rcS.d

El directorio init.d contiene todos los ejecutables de los servicios y demonios. Estos son enlazados desde los directorios de los niveles de arranque de dos maneras; de inicio o de parada.

  • Los enlaces de inicio (Start) tienen el aspecto S24pcmcia, donde la S mayúscula hace que el servicio reciba señal de inicio (start), los números fijan un orden de ejecución, y el nombre del servicio es la última parte del enlace.
  • Los enlaces que indican parada usan la misma convención de nombres con una K mayúscula en lugar de la S. La presencia de dicha K hace que los servicios se ejecuten con señal stop para que de forma ordenada se detengan.

Ejemplo de contenido de /etc/rc2.d. Nivel de arranque 2:

ls -l /etc/rc2.d/
total 4
-rw-r--r-- 1 root root 556 2009-03-31 10:02 README
lrwxrwxrwx 1 root root  19 2009-08-06 21:50 S01policykit -> ../init.d/policykit
lrwxrwxrwx 1 root root  15 2009-08-06 21:50 S10acpid -> ../init.d/acpid
lrwxrwxrwx 1 root root  14 2009-08-06 21:50 S10apmd -> ../init.d/apmd
lrwxrwxrwx 1 root root  18 2009-08-06 21:50 S10sysklogd -> ../init.d/sysklogd
lrwxrwxrwx 1 root root  15 2009-08-06 21:50 S11klogd -> ../init.d/klogd
lrwxrwxrwx 1 root root  14 2009-08-06 21:50 S12dbus -> ../init.d/dbus
lrwxrwxrwx 1 root root  13 2009-08-05 21:47 S16ssh -> ../init.d/ssh
...

Ejemplo de contenido de /etc/rc6.d. Nivel de arranque 6 de reinicio:

$ ls -l /etc/rc6.d/
total 4
lrwxrwxrwx 1 root root  13 2009-08-06 21:50 K01gdm -> ../init.d/gdm
lrwxrwxrwx 1 root root  17 2009-08-06 21:50 K02usplash -> ../init.d/usplash
lrwxrwxrwx 1 root root  17 2009-09-20 17:09 K09apache2 -> ../init.d/apache2
lrwxrwxrwx 1 root root  16 2009-08-06 21:50 K20apport -> ../init.d/apport
lrwxrwxrwx 1 root root  23 2009-09-27 13:01 K20apt-cacher-ng -> ../init.d/apt-cacher-ng
lrwxrwxrwx 1 root root  17 2009-09-18 16:03 K20vboxdrv -> ../init.d/vboxdrv
lrwxrwxrwx 1 root root  24 2009-09-18 10:29 K20virtualbox-ose -> ../init.d/virtualbox-ose
lrwxrwxrwx 1 root root  36 2009-09-18 10:30 K20virtualbox-ose-guest-utils -> ../init.d/virtualbox-ose-guest-utils
lrwxrwxrwx 1 root root  17 2009-09-23 12:31 K20winbind -> ../init.d/winbind
lrwxrwxrwx 1 root root  24 2009-09-23 15:12 K21postgresql-8.3 -> ../init.d/postgresql-8.3
lrwxrwxrwx 1 root root  20 2009-08-06 21:50 K25hwclock.sh -> ../init.d/hwclock.sh
lrwxrwxrwx 1 root root  20 2009-08-06 21:50 K50alsa-utils -> ../init.d/alsa-utils
lrwxrwxrwx 1 root root  26 2009-08-06 21:50 K63mountoverflowtmp -> ../init.d/mountoverflowtmp
lrwxrwxrwx 1 root root  19 2009-08-06 21:50 K74bluetooth -> ../init.d/bluetooth
lrwxrwxrwx 1 root root  21 2009-08-06 21:50 K99laptop-mode -> ../init.d/laptop-mode
-rw-r--r-- 1 root root 351 2009-03-31 10:01 README
lrwxrwxrwx 1 root root  41 2009-08-06 21:50 S01linux-restricted-modules-common -> ../init.d/linux-restricted-modules-common
lrwxrwxrwx 1 root root  22 2009-08-06 21:50 S15wpa-ifupdown -> ../init.d/wpa-ifupdown
lrwxrwxrwx 1 root root  18 2009-08-06 21:50 S20sendsigs -> ../init.d/sendsigs
lrwxrwxrwx 1 root root  17 2009-08-06 21:50 S30urandom -> ../init.d/urandom
lrwxrwxrwx 1 root root  22 2009-08-06 21:50 S31umountnfs.sh -> ../init.d/umountnfs.sh
lrwxrwxrwx 1 root root  20 2009-08-06 21:50 S35networking -> ../init.d/networking
lrwxrwxrwx 1 root root  18 2009-08-06 21:50 S40umountfs -> ../init.d/umountfs
lrwxrwxrwx 1 root root  20 2009-08-06 21:50 S60umountroot -> ../init.d/umountroot
lrwxrwxrwx 1 root root  16 2009-08-06 21:50 S90reboot -> ../init.d/reboot
Un nivel de arranque, por tanto, no deja de ser un conjunto de servicios y programas que se lanzan o se detienen en un orden adecuado para evitar problemas de dependencias.

Para alterar la configuración de los scripts de inicio y parada de los diferentes niveles de arranque en Ubuntu desde la línea de comandos utilizamos update-rc.d.

La ventaja de usar este script es que se encargará de añadir y eliminar los enlaces requeridos a /etc/init.d de forma automática.

Si queremos ver en que niveles se inicia y detiene el servidor web apache2 lo podemos hacer ejecutando:

# ls -l /etc/rc?.d/*apache2
lrwxrwxrwx 1 root root 17 2007-07-05 22:51 /etc/rc0.d/K91apache2 -> ../init.d/apache2
lrwxrwxrwx 1 root root 17 2007-07-05 22:51 /etc/rc1.d/K91apache2 -> ../init.d/apache2
lrwxrwxrwx 1 root root 17 2007-07-05 22:51 /etc/rc2.d/S91apache2 -> ../init.d/apache2
lrwxrwxrwx 1 root root 17 2007-07-05 22:51 /etc/rc3.d/S91apache2 -> ../init.d/apache2
lrwxrwxrwx 1 root root 17 2007-07-05 22:51 /etc/rc4.d/S91apache2 -> ../init.d/apache2
lrwxrwxrwx 1 root root 17 2007-07-05 22:51 /etc/rc5.d/S91apache2 -> ../init.d/apache2
lrwxrwxrwx 1 root root 17 2007-07-05 22:51 /etc/rc6.d/K91apache2 -> ../init.d/apache2

Como podemos ver tenemos una K al comienzo del enlace para los niveles de arranque 0, 1, 6 (apagado, monousuario y reinicio) y para los niveles 2, 3, 4 y 5 (niveles multiusuario en Debian Ubuntu) los enlaces empiezan por S que como hemos visto provocan que init les envíe una señal de inicio (start).

Eliminando un servicio

Si quisieramos deshabilitar apache2 completamente a mano tendríamos que borrar cada enlace contenido en /etc/rcX.d/. Utilizando update-rc.d es tan simple como:

# update-rc.d -f apache2 remove

La opción -f fuerza la eliminación de los enlaces simbólicos aunque exista /etc/init.d/apache2.

Añadiendo un servicio

Si queremos que un servicio se inicie al arrancar podemos ejecutar:

# update-rc.d apache2 defaults
Adding system startup for /etc/init.d/apache2 ...
/etc/rc0.d/K20apache2 -> ../init.d/apache2
/etc/rc1.d/K20apache2 -> ../init.d/apache2
/etc/rc6.d/K20apache2 -> ../init.d/apache2
/etc/rc2.d/S20apache2 -> ../init.d/apache2
/etc/rc3.d/S20apache2 -> ../init.d/apache2
/etc/rc4.d/S20apache2 -> ../init.d/apache2
/etc/rc5.d/S20apache2 -> ../init.d/apache2

defaults aplica las opciones por defecto del servicio. Se inicia en los niveles de arranque 2, 3, 4 y 5 y se detiene en 0, 1 y 6 con orden 20.

Estableciendo prioridades

Como podemos ver en el caso anterior, la prioridad por defecto vale 20 que puede no servirnos si el servicio depende de otros que se lanzan con prioridad menor. Si queremos ponerle de orden de prioridad 91:

# update-rc.d apache2 defaults 91
Adding system startup for /etc/init.d/apache2 ...
/etc/rc0.d/K91apache2 -> ../init.d/apache2
/etc/rc1.d/K91apache2 -> ../init.d/apache2
/etc/rc6.d/K91apache2 -> ../init.d/apache2
/etc/rc2.d/S91apache2 -> ../init.d/apache2
/etc/rc3.d/S91apache2 -> ../init.d/apache2
/etc/rc4.d/S91apache2 -> ../init.d/apache2
/etc/rc5.d/S91apache2 -> ../init.d/apache2

Diferentes prioridades de inicio y parada

Si queremos establecer diferentes prioridades de inicio y de parada, por ejemplo 20 de inicio y 80 de parada, ejecutaríamos:

# update-rc.d apache2 defaults 20 80
Adding system startup for /etc/init.d/apache2 ...
/etc/rc0.d/K80apache2 -> ../init.d/apache2
/etc/rc1.d/K80apache2 -> ../init.d/apache2
/etc/rc6.d/K80apache2 -> ../init.d/apache2
/etc/rc2.d/S20apache2 -> ../init.d/apache2
/etc/rc3.d/S20apache2 -> ../init.d/apache2
/etc/rc4.d/S20apache2 -> ../init.d/apache2
/etc/rc5.d/S20apache2 -> ../init.d/apache2

Como hemos visto, El demonio init actual (primer proceso del sistema y padre de todos los procesos)se basa en el del UNIX System V, por lo que se le conoce como sysvinit. Los sistemas operativos que siguen este esquema clasifican las tareas en diferentes “run levels” o niveles de ejecución, y se lanzaran una serie de servicios y demonios dependiendo del nivel de ejecución (o arranque) que hayamos seleccionado.

Ejecutar una serie fijada de scripts, uno tras otro, en un determinado orden ha funcionado razonablemente bien hasta ahora. No obstante, conforme Linux ha ido mejorando y adáptandose a los sistemas modernos (posiblemente el manejo de dispositivos desmontables es mejor en Linux que en Windows) este enfoque ha empezado a plantear problemas.

La antigua solución sólo funciona si garantizamos que en determinados instantes de la secuencia de arranque están disponibles ciertos recursos, por ello para que los scripts de init funcionen se deben ejecutar en puntos concretos de dicha secuencia. Normalmente se ordenan teniendo en cuenta que:

  • Los discos duros deben haberse encontrado, iniciado y haber detectado sus particiones antes de que intentemos montarlas desde /etc/fstab.
  • Los dispositivos de red deben haberse detectado e iniciado antes de que activemos los servicios de red.

Esto funcionaba hace diez años, ¿por qué ahora no? La respuesta breve es que nuestras computadoras se han vuelto mucho más flexibles:

  • Los dispositivos pueden enchufarse y desenchufarse en cualquier momento, e.g. dispositivos USB.
  • Los buses de almacenamiento aceptan un número variable de dispositivos, por lo que hay que explorar el bus. Esta operación no debe ser bloqueante.
  • Para reducir el consumo eléctrico, las unidades de disco duro pueden dejar de girar hasta que se explore el bus, por lo que tardarán un tiempo mayor en aparecer.
  • Los dispositivos de red pueden enchufarse y desenchufarse en cualquier instante.

Hasta ahora se ha podido hackear el sistema para que gran parte de esto sea posible, pero ya era hora de diseñar un sistema nuevo que pudiera enfrentarse a todas estas situaciones sin problemas.

Necesitábamos un sistema init que pudiera reordenar dinámicamente la secuencia de inicio basándose en la configuración y el hardware disponible en cada situación.

Upstart es un demonio controlado por eventos. Los eventos generados por el sistema pueden iniciar una tarea y parar las que ya se están ejecutando. Los eventos pueden ser diversos, pueden ser cosas como:

  • Se ha iniciado el sistema
  • Se ha montado el sistema de ficheros raíz
  • Se ha montado un sistema de archivos
  • En un cierto momento o cada cierto tiempo
  • Se ha detectado un dispositivo de red.
  • etc.

De hecho, cualquier proceso del sistema puede enviar eventos a init, por lo que no hay límite en los eventos posibles.

Tal y como se ha dicho, los eventos generados por el demonio init o enviados por otros procesos a init, pueden provocar que las tareas se inicien o detengan. También pueden recibirse peticiones manuales para iniciar o parar una tarea.

Hay muchos administradores de sistemas que ya están acostumbrados al funcionamiento de Linux y no querrán aprender otra vez de nuevo. También hay una ingente cantidad de libros sobre el software actual y no se ocuparán de upstart hasta dentro de unos años.

Por este motivo, la compatibilidad es muy importante. Upstart continuará ejecutando los scripts del anterior sistema de arranque SysVinit, y seguira leyendo anteriores archivos de configuración como /etc/inittab en el futuro cercano, de manera que los paquetes no tendrán que actualizarse hasta que sus autores lo estimen oportuno.

Upstart ya se ha empezado a implementar en Ubuntu y Redhat y Debian tiene planes de incorporarlo en la próxima versión estable.

Si en el arranque SysV init se configura en /etc/inittab, upstart se configura en una serie de ficheros incluidos en la carpeta /etc/init:

$ ls /etc/init
acpid.conf               hwclock.conf                     network-manager.conf  tty3.conf
alsa-mixer-save.conf     hwclock-save.conf                nmbd.conf             tty4.conf
anacron.conf             irqbalance.conf                  plymouth.conf         tty5.conf
apport.conf              module-init-tools.conf           plymouth-log.conf     tty6.conf
atd.conf                 mountall.conf                    plymouth-splash.conf  udev.conf
avahi-daemon.conf        mountall-net.conf                plymouth-stop.conf    udev-finish.conf
console-setup.conf       mountall-reboot.conf             procps.conf           udevmonitor.conf
control-alt-delete.conf  mountall-shell.conf              rc.conf               udevtrigger.conf
cron.conf                mounted-dev.conf                 rcS.conf              ufw.conf
cups.conf                mounted-tmp.conf                 rc-sysinit.conf       upstart-udev-bridge.conf
dbus.conf                mounted-varrun.conf              rsyslog.conf          ureadahead.conf
dmesg.conf               mysql.conf                       screen-cleanup.conf   ureadahead-other.conf
failsafe-x.conf          networking.conf                  smbd.conf
gdm.conf                 network-interface.conf           tty1.conf
hostname.conf            network-interface-security.conf  tty2.conf

Por compatibilidad los servicios de Upstart se siguen enlazando en /etc/init.d para poder invocarlos de la manera tradicional. Para averiguar que servicios de los que aparecen en /etc/init.d ya han sido adaptados a Upstart podemos hacer listando el contenido de dicha carpeta y buscando aquellos que son enlaces simbólicos al archivo /lib/init/upstart-job

$ ls -l /etc/init.d | grep upstart-job
lrwxrwxrwx 1 root root   21 2011-12-08 18:27 acpid -> /lib/init/upstart-job
lrwxrwxrwx 1 root root   21 2011-10-11 08:28 alsa-restore -> /lib/init/upstart-job
lrwxrwxrwx 1 root root   21 2011-10-11 08:28 alsa-store -> /lib/init/upstart-job
lrwxrwxrwx 1 root root   21 2011-10-29 18:13 anacron -> /lib/init/upstart-job
lrwxrwxrwx 1 root root   21 2011-10-25 06:28 apport -> /lib/init/upstart-job
lrwxrwxrwx 1 root root   21 2011-10-29 18:13 atd -> /lib/init/upstart-job
lrwxrwxrwx 1 root root   21 2011-10-29 18:13 avahi-daemon -> /lib/init/upstart-job
lrwxrwxrwx 1 root root   21 2011-10-29 18:13 binfmt-support -> /lib/init/upstart-job
lrwxrwxrwx 1 root root   21 2011-10-29 18:13 console-setup -> /lib/init/upstart-job
lrwxrwxrwx 1 root root   21 2011-10-29 18:13 cron -> /lib/init/upstart-job
lrwxrwxrwx 1 root root   21 2011-12-05 06:25 cups -> /lib/init/upstart-job
lrwxrwxrwx 1 root root   21 2011-10-29 18:13 dbus -> /lib/init/upstart-job
lrwxrwxrwx 1 root root   21 2011-10-29 18:13 dmesg -> /lib/init/upstart-job
lrwxrwxrwx 1 root root   21 2011-10-29 18:13 friendly-recovery -> /lib/init/upstart-job
lrwxrwxrwx 1 root root   21 2011-09-23 23:33 gdm -> /lib/init/upstart-job
lrwxrwxrwx 1 root root   21 2011-10-29 18:13 hostname -> /lib/init/upstart-job
lrwxrwxrwx 1 root root   21 2011-10-29 18:13 hwclock -> /lib/init/upstart-job
lrwxrwxrwx 1 root root   21 2011-10-29 18:13 hwclock-save -> /lib/init/upstart-job
lrwxrwxrwx 1 root root   21 2011-10-29 18:13 irqbalance -> /lib/init/upstart-job
lrwxrwxrwx 1 root root   21 2012-03-05 01:33 lightdm -> /lib/init/upstart-job
lrwxrwxrwx 1 root root   21 2011-10-07 00:57 lxdm -> /lib/init/upstart-job
...
lrwxrwxrwx 1 root root   21 2012-01-09 17:15 udev -> /lib/init/upstart-job
lrwxrwxrwx 1 root root   21 2012-01-09 17:15 udev-fallback-graphics -> /lib/init/upstart-job
lrwxrwxrwx 1 root root   21 2012-01-09 17:15 udev-finish -> /lib/init/upstart-job
lrwxrwxrwx 1 root root   21 2012-01-09 17:15 udevmonitor -> /lib/init/upstart-job
lrwxrwxrwx 1 root root   21 2012-01-09 17:15 udevtrigger -> /lib/init/upstart-job
lrwxrwxrwx 1 root root   21 2011-10-29 18:13 ufw -> /lib/init/upstart-job

Los servicios que ya funcionan con el sistema Upstart se gestionan manualmente con los comandos:

  • start: para iniciar un servicio.
  • stop: para detener un servicio.
  • status: para comprobar su estado actual.
  • restart para reiniciar el servicio

Los servicios que han sido adaptados al nuevo sistema de arranque, como vimos, tienen su configuración en /etc/init

$ ls /etc/init
acpid.conf               networking.conf
alsa-restore.conf        network-interface.conf
alsa-store.conf          network-interface-security.conf
anacron.conf             network-manager.conf
apport.conf              nmbd.conf
atd.conf                 plymouth.conf
avahi-daemon.conf        plymouth-log.conf
binfmt-support.conf      plymouth-splash.conf
console-setup.conf       plymouth-stop.conf
control-alt-delete.conf  plymouth-upstart-bridge.conf
cron.conf                procps.conf
cups.conf                rc.conf
dbus.conf                rcS.conf
dmesg.conf               rc-sysinit.conf
failsafe.conf            rsyslog.conf
friendly-recovery.conf   setvtrgb.conf
gdm.conf                 smbd.conf
hostname.conf            ssh.conf
...

Ejemplos

Para ver el estado actual de un servicio (en este caso ssh):

$ sudo status ssh
ssh start/running, process 1016

Nos indica que el servicio ssh está arrancado y en ejecución. Nos informa además de su PID

Para detener un servicio:

$ sudo stop ssh
ssh stop/waiting

El servicio es detenido y queda a la espera de recibir otros eventos,

Para iniciar un servicio:

$ sudo start ssh
ssh start/running, process 3258

Para reiniciar un servicio lo podemos hacer mediante:

$ sudo restart ssh
ssh start/running, process 3264

Hay servicios que todavía no han sido adaptados al nuevo sistema de arranque upstart y que se gestionan mediante el anterior sistema de arranque SysV. Para gestionar manualmente dichos servicios lo hacemos de la forma:

$ sudo /etc/init.d/[servicio] start|stop|restart|status
  • servicio es el nombre del servicio a gestionar.
  • start|stop|restart|status son las señales que podemos enviar a los servicios.

Si ejecutamos el script del servicio sin especificarle ninguna señal nos suele informar de todas las señales que le podemos enviar. Estas pueden variar de un servicio a otro.

Ejemplos

Si queremos enviar diferentes tipos de señales al servicio web apache2 lo podemos hacer de la forma:

$ sudo /etc/init.d/apache2 status
Apache2 is running (pid 3306).

Permite ver el estado actual del servicio.

$ sudo /etc/init.d/apache2 stop
 * Stopping web server apache2
 ... waiting                                                             [ OK ]

Para detener el servicio.

$ sudo /etc/init.d/apache2 start
 * Starting web server apache2
                                                                         [ OK ]

Para iniciarlo

$ sudo /etc/init.d/apache2 restart
 * Restarting web server apache2
                                                                         [ OK ]

Para reiniciarlo.

Si queremos ver que señales se le pueden enviar a apache2 invocamos el script de inicio sin ninguna señal:

$ sudo /etc/init.d/apache2
 * Usage: /etc/init.d/apache2 {start|stop|graceful-stop|restart|reload|force-reload|start-htcacheclean|stop-htcacheclean|status}

Por compatibilidad, los servicios que han sido adaptados al nuevo sistema de arranque upstart pueden ser gestionados usando el sistema SysV, pero aperece entonces un mensaje de advertencia.

Por ejemplo, si queremos reiniciar el servicio cron, podemos usar el mecanismo de SysV Init:

$ sudo /etc/init.d/cron restart
Rather than invoking init scripts through /etc/init.d, use the service(8)
utility, e.g. service cron restart
 
Since the script you are attempting to invoke has been converted to an
Upstart job, you may also use the stop(8) and then start(8) utilities,
e.g. stop cron ; start cron. The restart(8) utility is also available.
cron stop/waiting
cron start/running, process 3468

Como vemos, reinicia el servicio, pero nos informa que podemos usar directamente el mecanismo provisto por Upstart:

$ sudo restart cron