Story Transcript
Niveles de Arranque Este material describe el proceso init, el cual es el primer nivel de procesos del usuario iniciado por el núcleo. init tiene muchos deberes importantes, como iniciar getty (lo que permite a los usuarios iniciar sesión), implementar niveles de arranque, y manipular cuidadosamente el control de los procesos huérfanos. Este material explica como init es configurado y como usted puede hacer uso de los diferentes niveles de ejecución. init es el padre de todos los procesos. Su papel primario es crear procesos a partir de un guión guardado en el archivo /etc/inittab (véase inittab(5)).
init es el primero init es uno de esos programas que son absolutamente esenciales para la operación de un sistema Linux, y que todavía puedes no conocerlo completamente. Una buena distribución de Linux vendrá con una configuración para el init que trabajará para la mayoría de los sistemas , y en esos sistemas no hay nada que necesites hacer sobre init. Generalmente, deberás preocuparte por init si manipulas terminales seriales, dial-in en los modems (no dial-out), o si deseas cambiar el nivel de arranque estándar. Cuando el núcleo ha iniciado por si mismo (ha sido cargado en memoria, ha iniciado el arranque, así como también ha iniciado todos los controladores de los dispositivos y estructuras de datos, entre otros), esto finaliza como una parte propia del proceso de arranque iniciando un programa del nivel de usuario, init. Así, init es siempre el primer proceso (su número de proceso siempre es 1). El núcleo busca init en algunas localizaciones que se han utilizado históricamente para él, pero la localización apropiada para ella (en un sistema de Linux) es /sbin/init. Si el núcleo no puede encontrar el init, intenta ejecutar /bin/sh, y si ése también falla, el arranque del sistema no será posible. Cuando init comienza, finaliza el proceso de inicio del sistema realizando un número de tareas administrativas, tales como comprobación de sistemas de archivos, limpieza de /tmp, iniciar varios servicios, y comenzar un getty para cada terminal y consola virtual donde los usuarios podrán iniciar una sesión. Después de que el sistema esté correctamente iniciado, init reinicia getty para cada terminal después de que un usuario ha terminado la sesión (de modo que el usuario siguiente pueda iniciar una sesión). init también adopta procesos huérfanos: cuando un proceso comienza un proceso hijo y muere antes que su proceso hijo, el hijo inmediatamente se convierte en un proceso hijo de init. Esto es importante por varias razones técnicas, pero es bueno saberlo, puesto que hace más fácil entender las listas de procesos y árbol de
procesos. Hay algunas variantes de init disponibles. La mayoría de las distribuciones Linux utilizan el sysvinit (escrito por Miquel van Smoorenburg), el cual está basado en el diseño de init del sistema V. Las versiones del DEB de Unix tienen un init diferente. La diferencia principal son los niveles de ejecución: El sistema V los tiene, BSD por el contrario, no (por lo menos tradicionalmente). Esta diferencia no es esencial. Miraremos el sysvinit solamente.
Configurando init para iniciar getty: el archivo /etc/inittab Cuando el sistema inicia, init lee el archivo de configuración /etc/inittab. Mientras el sistema está corriendo, éste releerá el archivo, si envía la señal HUP (kill -HUP 1); esta característica hace que sea innecesario reiniciar el sistema para que los cambios en el archivo de configuración sean asumidos por init. El archivo /etc/inittab es un poco complicado. Comenzaremos con un proceso sencillo de configurar las líneas de getty. Líneas en /etc/inittab consiste en cuatro campos delimitados por dos puntos: id:runlevels:action:process
Los campos serán descritos a continuación. Adicionalmente, /etc/inittab puede contener líneas vacías, y líneas que empiezan con el símbolo (`#'); ambas son ignoradas. id Éste identifica la línea en el archivo. En líneas de getty, éste especifica el terminal en que correrá (los caracteres después de /dev/tty en el nombre de archivo del dispositivo). Para otras líneas, no importa (excepto por restricciones de longitud), pero debe ser único. runlevels Especifica el nivel de ejecución donde será considerada la línea. Los niveles de arranque son indicados con dígitos simples, sin delimitadores. (Los niveles de ejecución serán descritos en la siguiente sección.) action Indica la acción que será tomada por la línea, e.g., respawn para reiniciar el proceso cuando termine, cuando éste exista, o once El proceso se ejecutará una vez cuando se entre en el nivel de ejecución especificado. process El comando a ser ejecutado.
Para iniciar un getty en la primera terminal virtual (/dev/tty1), en todos los niveles de ejecución multi-usuario (2-5), podrá ser escrito como en la siguiente línea: 1:2345:respawn:/sbin/getty 9600 tty1
El primer campo indica que es la línea para /dev/tty1. El segundo campo indica que ésta aplica para los niveles de ejecución 2, 3, 4, y 5. El tercer campo significa que el comando será reiniciado cuando termine, siempre y cuando exista (ésto permite iniciar una sesión, terminarla, y nuevamente iniciarla). El último campo es el comando a ser ejecutado getty en el primer terminal virtual. Diferentes versiones de getty corren de forma distinta. Consulte su página de manual, y asegúrese que está viendo la página de manual adecuada. Si usted está buscando agregar terminales o acceder al sistema a través de una llamada por módem entrante, deberá agregar más líneas al archivo /etc/inittab, una por cada terminal o llamada entrante. Para mayores detalles, vea las páginas de manual init, inittab y getty. Si un comando falla mientras se está iniciando, e init es configurado para restart (reiniciarlo), este utilizará una gran cantidad de recursos del sistema: init lo inicia, éste falla, init lo inicia, éste falla, init lo inicia, éste falla, y así sucesivamente, hasta el infinito. Para prevenir ésto, init no perderá de vista cuantas veces se reinicia un comando, y si la frecuencia se hace alta, generará un retraso de cinco minutos antes de recomenzar otra vez.
Niveles de ejecución Un nivel de ejecución es el estado de init y de todo el sistema que define que servicios están operando en el sistema. Los niveles de ejecución son identificados por números. Algunos administradores de sistemas utilizan los niveles de ejecución para definir que subsistemas están trabajando, por ejemplo: si X está ejecutándose, si la red está operativa, y así sucesivamente. Otros tienen todos los subsistemas siempre ejecutándose o los inician y detienen individualmente, sin cambiar los niveles de ejecución, puesto que los niveles de ejecución son demasiados gruesos para controlar sus sistemas. Usted necesita decidir por usted mismo, pero puede ser que la manera más fácil a seguir sea la manera como su distribución de Linux hace cosas. La siguiente tabla define como la mayoría de las distribuciones Linux define los diferentes niveles de ejecución. Sin embargo, los niveles de ejecución del 2 al 5 pueden ser modificados para satisfacer sus propios gustos. Números de niveles de ejecución 0 Detener el sistema. 1 Modo mono usuario (single-user mode) (para administración especial). 2 Multiusuario local con soporte de red pero sin servicios de red, por ejemplo, NFS.
3 Multiusuario con soporte de servicios de red. 4 No utilizado 5 Multiusuario con soporte de servicios de red y sistema X Windows(GUI) 6 Reinicio. Servicios que pueden ser iniciados por un determinado tiempo de ejecución están determinados por el contenido de varios directorios rcN.d. Muchas distribuciones localiza estos directorios directorios cualquieras en /etc/init.d/rcN.d o /etc/rcN.d. (Reemplace la N con el número del nivel de ejecución.) En cada nivel de ejecución usted podrá encontrar una serie de enlaces que apuntan a scripts de inicio localizados en /etc/init.d. Todos los nombres de estos enlaces empiezan por una K o S, seguido por un número. Si el nombre de un enlace inicia con una S, esto indica que el servicio será iniciado cuando el equipo se encuentra en ese nivel de ejecución. Si el nombre de un enlace inicia con una K, el servicio será terminado (si está ejecutándose). El número siguiente a la K o S indica el orden que los scripts serán ejecutados. Éste es un ejemplo de un directorio /etc/init.d/rc3.d # ls -l /etc/init.d/rc3.d lrwxrwxrwx 1 root root 10 lrwxrwxrwx 1 root root 6 lrwxrwxrwx 1 root root 9 lrwxrwxrwx 1 root root 9 lrwxrwxrwx 1 root root 11 lrwxrwxrwx 1 root root 10 lrwxrwxrwx 1 root root 9 lrwxrwxrwx 1 root root 10 lrwxrwxrwx 1 root root 9 lrwxrwxrwx 1 root root 6 lrwxrwxrwx 1 root root 12 lrwxrwxrwx 1 root root 8 lrwxrwxrwx 1 root root 7 lrwxrwxrwx 1 root root 8 lrwxrwxrwx 1 root root 7 lrwxrwxrwx 1 root root 6 lrwxrwxrwx 1 root root 13 lrwxrwxrwx 1 root root 9 lrwxrwxrwx 1 root root 7 lrwxrwxrwx 1 root root 10 lrwxrwxrwx 1 root root 6 lrwxrwxrwx 1 root root 7 lrwxrwxrwx 1 root root 8
2004-11-29 2005-03-29 2004-11-29 2004-11-29 2005-03-01 2004-11-29 2004-11-29 2004-11-29 2004-11-29 2004-11-29 2004-11-29 2004-11-29 2004-11-29 2005-02-01 2004-12-02 2004-11-29 2004-11-29 2004-11-29 2004-11-29 2004-11-29 2005-02-04 2004-11-29 2004-12-22
22:09 13:42 22:08 22:06 11:56 22:34 22:07 22:09 22:07 22:09 22:40 22:09 22:10 09:24 20:34 22:09 22:10 22:09 22:10 22:10 13:27 22:10 20:35
K12nfsboot -> ../nfsboot K15xdm -> ../xdm S01pcmcia -> ../pcmcia S01random -> ../random S02firewall -> ../firewall S05network -> ../network S06syslog -> ../syslog S08portmap -> ../portmap S08resmgr -> ../resmgr S10nfs -> ../nfs S12alsasound -> ../alsasound S12fbset -> ../fbset S12sshd -> ../sshd S12xntpd -> ../xntpd S13cups -> ../cups S13kbd -> ../kbd S13powersaved -> ../powersaved S14hwscan -> ../hwscan S14nscd -> ../nscd S14postfix -> ../postfix S14smb -> ../smb S15cron -> ../cron S15smbfs -> ../smbfs
Como se ejecutan los niveles de inicio son configurados en el archivo /etc/inittab por líneas como la siguiente: l2:2:wait:/etc/init.d/rc 2
El primer campo es una etiqueta arbitraria, el segundo significa que aplica para el nivel de ejecución 2. El tercer campo significa que init deberá ejecutar el comando cuando se entre el nivel indicado en el cuarto campo, y que init debe esperar por éste para completarse. El comando /etc/init.d/rc ejecuta los comandos que sean necesarios para iniciar y detener los servicios para entrar al nivel de ejecución 2.
El comando en el cuarto campo indica todo el trabajo duro de configurar el trabajo e iniciar un nivel de ejecución. Éste inicia servicios que no están ejecutándose actualmente , y detiene servicios que no deben funcionar en el nuevo nivel de ejecución y más. Exactamente que hace el comando, y como se ejecutan los niveles configurados, depende de la distribución Linux. Cuando init arranca, ésto puede verse en una línea de /etc/inittab que especifique el nivel de ejecución establecido: id:2:initdefault:
Usted puede indicar que init inicie un nivel de arranque no establecido por defecto a través del paso de argumentos al núcleo single o emergency. La línea de comandos del núcleo pueden ser suministrados via LILO, por ejemplo. Esto le permite seleccionar el modo mono usuario (single user mode) ejecutar el sistema en nivel 1. Mientras el sistema está ejecutándose, el comando telinit permite cambiar el nivel de ejecución. Cuando el nivel de ejecución es cambiado, init ejecuta los comandos relevantes de /etc/inittab.
Configuración especial en /etc/inittab El archivo /etc/inittab tiene algunas características especiales que le permite a init reaccionar a circunstancias especiales. Estas características especiales son marcadas por palabras claves especiales en el tercer campo. Algunos ejemplos: powerwait Permite a init apagar el sistema, cuando la alimentación de corriente falla. Esto asume que se está usando un UPS, y el software que controla el UPS informa a init que el sistema debe ser apagado. ctrlaltdel Permite a init reiniciar el sistema, cuando el usuario presione ctrl-alt-del en una consola de teclado. Note que el administrador del sistema puede configurar la reacción de ctrl-alt-del para hacer algo en lugar de otra cosa, por ejemplo, ser ignorado, si el sistema está en una ubicación pública. (O a iniciar nethack.) sysinit Comando a ser ejecutado cuando el sistema está iniciado. Este comando usualmente limpia /tmp, por ejemplo. Esta lista no muestra todas las configuraciones especiales. Vea su manual de inittab para observar todas las posibilidades, y para detalles para saber
como utilizar cada una de ellas.
Iniciando en modo mono usuario Un nivel de ejecución importante es el modo mono usuario (nivel de ejecución 1), en el cual solo el administrador del sistema puede utilizar el sistema y unos pocos servicios, incluyendo inicio de sesión, como posible estén ejecutándose. El modo monousuairo es para algunas tareas administrativas, como por ejemplo ejecutar fsck en una partición /usr, donde éste requiere que la partición sea desmontada, lo cual no es posible, a menos que todos los servicios sean detenidos (matados, killed). Un sistema en ejecución puede pasar a modo monousuario haciendo uso de telinit para responder a un cambio de nivel 1. En el momento de inicio, se le puede indicar al sistema que lo haga a través de la palabra single o emergency en la línea de comandos del núcleo: el núcleo obtiene la línea de comando y se la pasa a init como tal, init entiende la palabra como una instrucción que forza a no utilizar la configuración establecida para el nivel de ejecución del sistema. (La línea de comandos del núcleo es indicada en una forma particular para cada sistema.) Arrancando en modo monousuario en algunas ocasiones es necesario cuando se requiere iniciar fsck a mano, antes de que cualquier cosa monte o de otra manera toque una partición rota /usr (cualquier actividad en un systema de archivos roto es probable quebrarlo más, así que el fsck se debe ser ejecutado cuanto antes). Los scripts de arrranque init se ejecutarán automáticamente ingresando en modo monousuario, si el inicio automático de fsck falla en una secuencia de arranque. Esto es un intento de prevención a usar un sistema de archivos que esté roto y que fsck no puede reparar automáticamente. Tal ruptura es poco frecuente, ya que implica generalmente un disco duro dañado o una actualización experimental del núcleo, indistintamente es recomendable su reparación manual. Como medida de seguridad, una configuración adecuada del sistema deberá preguntar la contraseña de administrador antes de iniciar un intérprete de comandos en modo monousuario. De lo contrario, sería sencillo incorporar una línea conveniente en el gestor de arranque para ingresar al sistema como administrador. (Esto será fácil de realizar si /etc/passwd ha estado dañado por problemas del sistema de archivos, por supuesto, o en el caso de tener un disco de arranque a mano.)
El proceso de arranque de Debian El programa init Al igual que todos los sistemas Unix, Debian arranca ejecutando el programa init. El archivo de configuración de init (que es el /etc/inittab) indica que el primer script que se debe ejecutar es el /etc/init.d/rcS. Lo que ocurre a continuación depende de si se encuentra instalado el paquete sysv-rc o el file-rc. A continuación, supondremos que se encuentra instalado el paquete sysv-rc (file-rc contiene su propio script /etc/init.d/rcS y utiliza un archivo en vez de enlaces simbólicos en los directorios rc para controlar qué servicios se inician en los diferentes niveles de ejecución) El archivo /etc/init.d/rcS del paquete sysv-rc ejecuta todos los scripts situados en /etc/rcS.d/ para realizar inicializaciones tales como la comprobación y montaje de los sistemas de archivos, la carga de módulos, la inicialización de los servicios de red, la configuración del reloj, etc. Luego, y por compatibilidad, también ejecuta todos los archivos (excepto aquellos con un `.' en su nombre) situados en /etc/rc.boot/. Este último directorio está reservado para el administrador del sistema y su utilización ha caído en desuso. Debian utiliza el sistema de scripts sys-V. Aunque todos los scripts init en /etc/init.d/* están marcados como archivos de configuración y el administrador del sistema tiene la libertad de modificarlos, es preferible personalizarlos editando los archivos /etc/default/*. Por ejemplo, /etc/init.d/rcS se puede usar para personalizar los valores predeterminados de arranque de motd, sulogin, etc. Debian no utiliza el directorio rc.local del tipo BSD. Tras llamar a init como el último paso de la secuencia de carga del núcleo, busca el fichero /etc/inittab para ver si hay una entrada del tipo initdefault (véase inittab(5)). La entrada initdefault determina el nivel de ejecución inicial del sistema. Si no está esa entrada (o no existe /etc/inittab), se debe introducir un nivel de ejecución en la consola del sistema. El nivel de ejecución S o s lleva al sistema al modo monousuario y no requiere un fichero /etc/initttab. En modo monousuario, se llama a /sbin/sulogin en /dev/console. Cada vez que un hijo termina, init registra el hecho y la razón de su muerte en /var/run/utmp y /var/log/wtmp, suponiendo que estos ficheros existen.
Niveles de ejecución Luego de completar el proceso de arranque, init inicia todos los servicios que han sido configurados para ejecutarse en el nivel de ejecución predeterminado. Este último viene indicado por una entrada id en el /etc/inittab. Debian viene con id=2. Debian utiliza los siguientes niveles de ejecución:
•
1 (modo monousuario),
•
2 al 5 (modos multiusuario) y
•
0 (apagar el sistema),
•
6 (reiniciar el sistema).
También puede utilizarse los niveles de ejecución 7, 8 y 9 pero sus directorios rc no se van llenando a medida que son instalados los paquetes. Realmente no están documentados. Esto es porque las variantes Unix tradicionales no los usan. En caso de que sea curioso, los niveles de ejecución S y s son de hecho el mismo. Internamente se les renombra para el mismo nivel de ejecución. Cambie los niveles de ejecución utilizando el comando telinit. Al entrar a un nivel de ejecución se ejecutan todos los scripts ubicados en /etc/rcnivel_de_ejecución.d/. La primera letra del nombre del script determina la manera en que se ejecuta el script: Los scripts cuyos nombres comienzan con K se ejecutan con el argumento stop. Los scripts que comienzan con S se ejecutan con el argumento start. Los scripts se ejecutan de acuerdo al orden alfabético de sus nombres; de esta manera los scripts "stop" se ejecutan antes que los scripts "start" y los dos dígitos a continuación de K o S determinan el orden en que se ejecutan los scripts. Los scripts situados en /etc/rcnivel_de_ejecución son de hecho sólo enlaces simbólicos que apuntan a los scripts situados en /etc/init.d/ Cada script también acepta como argumento "restart" y "force-reload"; estos métodos se pueden utilizar para reiniciar los servicios una vez que haya sido arrancado el sistema o forzarlos para que vuelvan a cargar sus archivos de configuración. Por ejemplo: # /etc/init.d/exim4 force-reload
Personalizando los niveles de ejecución La personalización de los niveles de ejecución es una tarea avanzada del administrador del sistema. Los siguientes consejos son válidos para la mayoría de los servicios. Para habilitar el servicio servicio en el nivel de ejecución R cree el enlace simbólico /etc/rcR.d/Sxyservicio con objetivo ../init.d/servicio. El número de secuencia xy debe ser igual al asignado al servicio cuando fue instalado el paquete. Para deshabilitar un servicio, cambie de nombre el enlace simbólico de modo que su nombre comience con K y no con S y su número de secuencia sea 100 menos xy. Para estos fines, es conveniente usar un editor de niveles de ejecución tales como sysv-rc-conf o ksysv. En vez de cambiarle el nombre, es posible eliminar el enlace simbólico S de un servicio de un directorio de niveles de ejecución determinado. Esto no deshabilita el servicio sino que lo deja en un estado "potencial" al menos en lo que respecta al sistema init sysv-rc : al cambiar de nivel de ejecución el
servicio no se lo activará ni se lo detendrá sino que se lo dejará como estaba, independientemente si esta ejecutándose o no. Obsérvese, no obstante, que un servicio que está en este estado potencial se activará si se actualiza su paquete independientemente si estaba o no ejecutándose antes de la actualización. Este es un atajo conocido del sistema Debian actual. Nótese además que debería conservar los enlaces simbólicos K de un servicio en los niveles de ejecución 0 y 6. Si borra todos los enlaces simbolicos de un servicio, entonces al actualizar el paquete del mismo restaurará todos los enlaces simbólicos a su estado predeterminado de fábrica. No es aconsejable realizar modificaciones a los enlaces simbólicos situados en /etc/rcS.d/
Cambio de nivel de ejecución Tras haber lanzado todos los procesos especificados, init espera a que alguno de sus procesos descendientes muera, una señal de fallo de alimentación o hasta que se le indique por telinit que cambie el nivel de ejecución del sistema. Cuando alguna de las tres condiciones anteriores ocurre, re-examina el fichero /etc/inittab. Se pueden añadir nuevas entradas a este fichero en cualquier momento. Sin embargo, init aun espera a que alguna de las tres condiciones anteriores suceda. Para proporcionar una respuesta inmediata, telinit Q o el parámetro q puede levantar init para que re-examine el fichero /etc/inittab. Si init no está en modo monousuario una señal de fallo de alimentación, llamaran las entradas especiales powerfail. Cuando se le solicita a init que cambie el nivel, envía la señal de aviso SIGTERM a todos los procesos que no están definidos en el nuevo nivel de ejecución. Espera 5 segundos antes de forzar la terminación de estos procesos mediante la señal SIGKILL. Observe que init supone que todos estos procesos (y sus descendientes) permanecen en el mismo grupo de procesos que init creó originalmente para ellos. Si cualquier proceso cambia la afiliación de grupo de proceso no recibirá estas señales. Tales procesos necesitan ser terminados de forma separada.
El programa telinit /sbin/telinit está enlazado con /sbin/init. Toma un argumento de un solo carácter y señala a init para realizar la acción apropiada. Los siguientes argumetos sirven como directivas para telinit: 0,1,2,3,4,5 o 6 indica a init que cambie al nivel de ejecución especificado. a,b,c indica
a
init
que
procese
sólo
las
entradas
del
fichero
/etc/inittab que tengan nivel de ejecución a,b o c. Qoq indica a init que re-examine el fichero /etc/inittab. Sos indica a init que cambie a modo monousuario. Uou indica a init que reejecute él mismo (guardando el estado). No reexamining el fichero /etc/inittab. El nivel de ejecución debería ser uno de Ss12345, en otro caso la solicitud sería ignorada silenciosamente. telinit también puede decir a init cuanto esperará entre los envíos a los procesos de las señales SIGTERM y SIGKILL. El valor por defecto es 5 segundos, pero se puede cambiar con la opción -t sec. telinit sólo se puede llamar por usuarios con los privilegios apropiados. El binario init comprueba si es init o telinit mirando a su id de proceso; el id del proceso init real es siempre 1. De esto podemos concluir que en lugar de llamar a telinit se puede usar init en su lugar como abreviatura.