Upstart es el sistema que muchas distribuciones Linux utilizan para gestionar las tareas a realizar en el arranque. Para los más veteranos del lugar, Upstart tiene como objetivo reemplazar los daemons tradicionales de SystemV que gestionan las tareas a ejecutar en el arranque, la parada y puesta en marcha de servicios.
Upstart busca sustituir al daemon init, el primer proceso que se lanza en Linux tras cargar el kernel y que se encarga de arrancar el resto. init es el proceso padre de todos aquellos procesos que hayan perdido a su padre (es el padre de todos los daemons). El comando pstree permite ver esto gráficamente.
Por qué Upstart
init es un proceso síncrono que bloquea la ejecución de tareas hasta terminar con la actual. Las tareas que init debe ejecutar han de ser definidas con antelación y éstas sólo se ejecutan cuando init cambia su estado (generalmente porque la máquina se ha encendido, se está apagando o se está reiniciando). El daemon init decide qué tareas ejecutar al cambiar su estado (RUNLEVEL) mirando en el directorio /etc/rcX.d/, donde X indica el RUNLEVEL actual.
Este hecho impide que init gestione correctamente otras tareas que son necesarias ejecutar NO al cambiar de RUNLEVEL sino cuando se generan ciertos eventos, como por ejemplo, las siguientes:
* se quiere ejecutar un backup del servidor de la base de datos en cuanto se detecte que dicho servicio se ha parado
* se conecta en caliente un dispositivo USB o disco externo
* se quiere realizar un sondeo de los dispositivos de almacenamiento disponibles sin que se bloquee el sistema (especialmente cuando el disco a sondear está en estado stand-by y se enciende al detectar el sondeo)
* se quiere ejecutar un script cada hora pero sólo si la ejecución anterior ya ha terminado
Hay más ejemplos y casos de uso en la discusión para reemplazar init en Ubuntu.
El modelo basado en eventos de Upstart permite responder de forma asíncrona a eventos como los mencionados, en cuanto éstos ocurren. La asincronía permite poder ejecutar en paralelo distintas tareas con el objetivo de minimizar el tiempo de arranque.
Evolución de Upstart
Desde su introducción en Ubuntu 6.10 (2006) Upstart ha ido paulatinamente reemplazando a SystemV (la migración por pasos siempre fue un objetivo). Los scripts de arranque y parada de servicios han sido migrados, si no todos, si una buena parte. El fichero /etc/inittab que indicaba al proceso init qué RUNLEVEL arrancar por defecto y cuáles eran los scripts rc que había que arrancar en cada nivel, ha sido eliminado.
En las primeras versiones de Upstart, la definición de jobs (trabajos a realizar cuando se detecten ciertos eventos) se hacía en el directorio /etc/event.d. En Karmic Koala (9.10), Canonical decidió cambiar esa localización a /etc/init.
En Agosto de 2011, Red Hat decidió también adoptar Upstart, dejando de lado SystemV init.
Trabajos, eventos, tareas y servicios
Los trabajos (o jobs, en terminología Upstart) pueden ser tareas o servicios. Las tareas son simples scripts que se ejecutan y terminan su trabajo en un breve lapso de tiempo. Los servicios son procesos que se quedan en ejecución (daemons). Para que un job pueda ponerse en marcha o pararse, deben darse ciertas condiciones. Normalmente estas condiciones vienen dadas por la detección o no de ciertos eventos. Por poner un ejemplo gráfico, veamos el job /etc/init/mysql.conf que permite lanzar o parar mysql en función de la detección de ciertos eventos.
# MySQL Service description "MySQL Server" author "Mario Limonciello <superm1@ubuntu.com>" start on (net-device-up and local-filesystems and runlevel [2345]) stop on runlevel [016] [...] exec /usr/sbin/mysqld [...] |
En resumidas cuentas, el job mysql viene a decir que el daemon mysqld se pondrá en marcha cuando se detecte red (net-device-up), el sistema de ficheros haya sido montado (local-filesystems) y el nivel de ejecución sea uno entre 2 y 5 (Ubuntu en modo gráfico arranca por defecto en el nivel 2). Si se detecta un evento runlevel 0 ó 1 ó 6 entonces el daemon mysqld se parará.
En Ubuntu Natty, Upstart introdujo el comando initctl2dot, que permite ver gráficamente estas dependencias (además de ayudarnos a detectar quién emite cada evento en cuestión).
Por ejemplo, tecleando:
initctl2dot -r mysql -o - | dot -Tpng -o upstart.png
Obtenemos la siguiente imagen:
Los jobs se muestran en cajas grises. Las líneas azules apuntan a los eventos cuya emisión arrancarían el job. Las líneas rojas indican qué eventos provocarían la parada de mysql. Las líneas verdes unen un evento con el job que lo emite.
Si te preguntas quién emite net-device-up (en el diagrama no hay ningún job que lo emita), puedes realizar una búsqueda desde /etc así:
/etc/$ grep -irn "net-device-up" * |
y verás que lo hace el script if-up cada vez que se activa una tarjeta de red.
Emitir manualmente un evento
Tal y como se aprecia en la imagen anterior, es posible forzar la emisión de un evento. Para ello, desde la línea de comandos, basta con ejecutar:
$ sudo initctl emit nombre_del_evento |
Curiosidades
El primer evento que Upstart genera es startup.
Upstart tiene como uno de sus objetivos ser compatible con SysV init. Por ello, simula eventos runlevel y establece un DEFAULT_RUNLEVEL a través del job /etc/init/rc-sysinit.conf.
Muy buen articulo, pero mencionar systemd tampoco estaría mal 😉
Gracias Oier. Respecto a systemd… esta parte de la página wiki de Ubuntu me ha dado mieditorrr….
https://wiki.ubuntu.com/systemd#systemd_-_An_alternative_boot_manager
«Current versions of systemd require that you customize your kernel as well as running a non-standard init process. These are pretty intrusive changes.
Installing systemd may limit the amount of help and support available to you. If you have a commercial support agreement then installing systemd would almost certainly invalidate it. Even if you rely on forums etc, you will probably have to reproduce problems on a standard Ubuntu build before anyone can help you much.»
Resumiendo: There be Dragons…
Excelente entrada. Gracias.
– «Current versions of systemd require that you customize your kernel»
Bueno si han desactivado cgroups por defecto en el kernel tiene sentido que systemd no funcione. Pero teniendo en cuenta que es una funcionalidad muy interesante yo la activaría:
«cgroups (control groups) is a Linux kernel feature to limit, account and isolate resource usage (CPU, memory, disk I/O, etc.) of process groups.»
Un ejemplo famoso del uso que se le puede dar a cgroups surgió en el debate del famoso «parche milagro» que mejoraba el rendimiento de Linux cuando compilabas en un montón en terminales virtuales. Lo que el parche hacía era agrupar automaticamente todas las terminales virtuales en un grupo (a nivel del kernel). Y lo que Lennart comentaba, era que esto se podía/debía de hacer configurando bien los servicios del sistema a nivel de arranque. Es decir, agrupar por ejemplo servicios como dnsmasq, apache, etc… para que no roben ciclos a tareas que en un desktop serían más prioritarias como el Desktop.
De todas maneras esto está evolucionando muy rápido, y por ejemplo a partir de Gnome 3.2 systemd va a ser una dependencia externa. La razón es gnome-session va a ser «aumentado» por una instancia de systemd por usuario. Y es que esto introduce mejoras como la gestión de los cgroups que realiza systemd a nivel de escritorio, y además resuelve un problema dificil, como lo es arrancar los procesos de escritorio antes de hacer login (como el demonio que implementa la lógica para la suspensión de equipos, el wifi con network manager, las claves para el wifi, etc…).
– «Installing systemd may limit the amount of help and support available to you.»
Cierto, hay un montón de servicios que han dejado de usar scripts tradicionales para sólo instalar el servicio de upstart. Este es uno de los problemas que pretendía resolver en parte systemd evitando que muchos servicios requieran ficheros de configuración. Como por ejemplo que se puedan arrancar servicios por demanda al realizar llamadas a determinados puertos (como con el antiguo xinetd), o arrancar otros al recibir peticiones por d-bus (como el soporte bluetooth), etc…
Lo interesante del planteamiento de Lennart era que esto es una forma de describir las dependencias de algunos servicios de una manera más natural. Si no se piden, no arrancan, y no hace falta definir dependencias, dependencias de eventos, etc…
Por otro lado si usas un paquete de Ubuntu en Debian tienes el mismo problema. Tendrás que buscarte la vida con el script de arranque, porque muchos paquetes sólo distribuyen el fichero de upstart.
– «as running a non-standard init process. These are pretty intrusive changes»
Estos de Ubuntu… Esto ya me ha tocado el corazón. Jajaja. Porque aunque ellos digan eso, no es cierto, y lo digo con conocimiento de causa porque para depurar el arranque de Ubuntu en KestrelHPC he tenido que perder una ingente cantidad de tiempo… buff. El problema es que upstart sólo arranca si el init se ejecuta con el pid=0, y por lo tanto si arrancas el initial ramdisk en modo debug, no puedes arrancar init desde una terminal, te obliga a sustituir dicha terminal por init si o si, y si lo quieres evitar tienes que empezar a hacer unos líos…
Bueno concretamente en Kestrel nunca lo he conseguido. El sistema se cuelga en el arranque cuando usamos NFS4 y a día de hoy no he conseguido depurar el arranque. Y no te pongas a buscar información sobre como depurar el arranque… porque no hay. 🙂
Pero bueno, de todas maneras lo que buscan upstart o systemd ya va más allá de el simple arranque paralelo del sistema, cosa que por ejemplo Debian Squeeze consigue con los antiguos scripts de SysV añadiéndoles etiquetas en la cabecera con las dependencias. Por ejemplo upstart permite gestionar eventos de udev, de modo que si se carga una interfaz de red se puedan arrancar determinados servicios, o si enchufas un disco duro lo mismo… Y por ejemplo systemd gestionará cosas como el hostname, de modo que para cambiarlo, las aplicaciones tendrán ahora que hablar con systemd.
Lo bueno y malo, es que estamos abandonando un antiguo diseño en el que nos sentíamos todos muy cómodos, para entrar en una nueva era en que posiblemente no se pueda entrar sin un cambio de diseño, pero que nos va a hacer tener que estudiar mucho.
@Jonan, tenemos que charlar un rato sobre systemd en la FISS. El tema es muy interesante y lo que has escrito en el comentario da para muchos cafés 🙂 Además @oier seguro que se apuntaba si estuviera por aquí…
Disculpe donde han aprendido todo ese conocimiento que tiene de los sistemas?
hay alguna documentación (online/ o algún libro) que me puedan recomendar?
Me parece bastante interesante todo lo que mencionan.
La mayoría de los conocimientos que he adquirido de linux son en blogs o foros pero no he encontrado documentación más extensa o alguna guía.
La mejor página q conozco es ésta tldp.org
Gracias.
@Donald: cada post técnico suele venir acompañado de las fuentes en las que nos basamos para su redacción. Por ejemplo, en el caso de Upstart, enlazamos con el wiki de Ubuntu, donde se detallan las especificaciones. No obstante, para cualquier tema técnico relacionado con Linux, siempre es aconsejable buscar en los blogs de los autores (por ejemplo, éste blog de uno de los autores de Upstart, tiene abundante información al respecto: http://upstart.at/ ) Y por supuesto, libros… para conocer cuáles, haz una búsqueda sobre Safari o sobre Google Books, usando el buscador Google así: upstart Linux site:safaribooksonline.com
(eso buscará libros que contengan las palabras Linux y Upstart en los libros técnicos de Safari (también puedes buscar en O’Reilly, Amazon, etc..)
Tengo un script de Python que levanta un servidor xmlrpc que es parte de una aplicación mayor; el problema que tengo es que no se como hacer para iniciar el script en el arranque del sistema.
Hice un archivo de prueba llamado «prueba.py» que solo imprime una linea, a este le hice un archivo «prueba.conf» y lo situe en «/etc/init» con los permisos y todo, luego doy el comando «sudo initctl reload-config» y cuando doy «sudo prueba start» no sucede nada, en los mensajes de «dmesg» sale: «init: Failed to spawn prueba main process: unable to execute: Permission denied»; no se si lo q me falta es darles permisos de ejecución al script de python o algo de eso, y tampoco se como hacerlo, gracias por cualquier ayuda y disculpen las molestias