SDB:Cómo crear scripts de inicio de forma normalizada
Este artículo hace referencia a la versión '{{{1}}}' y ahora está obsoleto. Mira en la página de discussion del artículo para más información. Si sigue obsoleto, podría ser eliminado. Si es posible, por favor ayuda a actualizar el artículo para hacerlo actual. |
Situación
- En ciertas ocasiones, necesitas crear tus propios scripts de arranque (init scripts), de forma que arranquen o no cierto demonio dependiendo del nivel de ejecución del sistema (runlevel).
- Te gustaría controlar cierto script haciendo uso de:
rc<nombredescript> {start|stop|status|reload|force-reload|try-restart|restart}
En este artículo se explicará cómo lograr esto, explicando además detenidamente todas las opciones de las que disponemos.
Procedimiento
El procedimiento es de lo más simple. Consta de 4 pasos simples:
- Copia la plantilla de init script que viene con openSUSE con el nombre que quieras darle:
cp /etc/init.d/skeleton /etc/init.d/<nombredescript>
- Edita el archivo
/etc/init.d/<nombredescript>
con algún editor de texto (como nano o kate) y lee y sigue las indicaciones. - Activa ahora tu script para que pueda ser arrancado en el arranque del sistema:
insserv /etc/init.d/<nombredescript>
- Finalmente, crea un enlace a
/sbin
:
ln -s /etc/init.d/<nombredescript> /sbin/rc<nombredescript>
Profundizando
Los pasos arriba mencionados son los necesarios para hacerte tu propio script de arranque, a continuación se detalla con más atención cuál sería la forma estricta de diseñar un script de arranque, de forma que podamos, por ejemplo, poder redistribuirlo luego en otro openSUSE; o en otro sistema Linux que respete también el estándar definido por la LSB (Linux Standard Base). Dicho estándar viene definido en el siguiente documento
Nomenclatura
Los nombres de los scripts de arranque deben cumplir el estándar marcado por la LSB, debiendo estar listado aquí . Para registrar un nuevo nombre de script, sigue el procedimiento que se explica aquí.
NOTA: Si no quieres llegar tan lejos, simplemente comprueba que el tuyo al menos no coincida con alguno de la lista, de esta forma evitarás posibles futuros conflictos.
Estructura
La estructura de un script de arranque está perfectamente definida en el script que nos sirve de plantilla (/etc/init.d/skeleton
). Este script lo encontramos por defecto en cualquier sistema openSUSE.
Los scripts de arranque, como cualquier otro script de shell, empiezan todos con la línea
#!/bin/sh
o bien
#!/bin/bash
Luego normalmente vemos muchas líneas de comentarios. Estas hacen mención a información relativa al autor, el copyright o la licencia. El archivo debe incluir una cabecera especial con meta información acerca del script. Mira las convenciones acerca de los comentarios para saber más acerca de esto. Mira también la lista de estados definidos que están definidos en openSUSE.
El siguiente ejemplo está sacado del script /etc/init.d/esound
:
# Copyright (c) 1995-2002 SUSE Linux AG, Nuernberg, Germany. # All rights reserved. # # Author: Stanislav Brabec, feedback to http://www.suse.de/feedback # ### BEGIN INIT INFO # Provides: esound # Required-Start: alsasound # Should-Start: $network portmap # Required-Stop: alsasound # Should-Stop: $network portmap # Default-Start: 5 # Default-Stop: # Short-Description: Sound daemon with network support # Description: Starts esound server to allow remote access to sound # card. To use esound locally, you do not need to start this # server on boot. You should edit server settings before # starting it via sysconfig editor: Network/Sound/Esound ### END INIT INFO
A continuación también encontramos definidos los chequeos que comprueban que el demonio está correctamente instalado, y que se encuentran disponibles los ficheros de configuración necesarios. En caso de problemas, deben retornarse en cada caso los códigos de error definidos en la LSB. Para más detalles mira aquí los códigos de salida.
Este es un ejemplo sacado del script /etc/init.d/ypbind
:
YPBIND_BIN=/usr/sbin/ypbind test -x $YPBIND_BIN || { echo "$YPBIND_BIN not installed"; if [ "$1" = "stop" ]; then exit 0; else exit 5; fi; } YPBIND_CONFIG=/etc/sysconfig/ypbind test -r $YPBIND_CONFIG || { echo "$YPBIND_CONFIG not existing"; if [ "$1" = "stop" ]; then exit 0; else exit 6; fi; } # Read config . $YPBIND_CONFIG
Más adelante también se definen las funciones de estado y se implementa el cambio de estado (rc). Este ejemplo está sacado del script /etc/init.d/network
:
. /etc/rc.status rc_reset
Luego se implementan las acciones requeridas por el script. Echa un vistazo a /etc/init/d/skeleton
, que viene con un código de ejemplo e incluye comentarios muy clarificadores. El siguiente ejemplo es un extracto del script /etc/init.d/cron
:
case "$1" in start) echo -n "Starting CRON daemon" startproc $CRON_BIN rc_status -v ;; stop) echo -n "Shutting down CRON daemon" killproc -TERM $CRON_BIN rc_status -v ;; try-restart) $0 status >/dev/null && $0 restart rc_status ;; restart) $0 stop $0 start rc_status ;; force-reload) echo -n "Reload service Cron" checkproc $CRON_BIN rc_status -v ;; reload) rc_status -v ;; status) echo -n "Checking for Cron: " checkproc $CRON_BIN rc_status -v ;; probe) ;; *) echo "Usage: $0 {start|stop|status|try-restart|\ restart|force-reload|reload|probe}" exit 1 ;; esac
Finalmente, los scripts de arranque deben terminar devolviendo el código de salida correcto. Por esto, el último comando suele ser la función rc_exit.
Convenciones acerca de los comentarios
Los scripts de inicio son como cualquier otro script de consola, los comentarios en el código se delimitan con el símbolo '#'
y pueden usarse sin limitaciones. Sólo hay una excepción; la LSB define un comentario especial de cabecera que proporciona cierta meta information acerca del script. Esta cabecera debe incluirse en todos los scripts de arranque y presenta la siguiente estructura:
### BEGIN INIT INFO # Provides: boot_facility_1 [ boot_facility_2 ...] # Required-Start: boot_facility_1 [ boot_facility_2 ...] # Should-Start: boot_facility_1 [ boot_facility_2 ...] # Required-Stop: boot_facility_1 [ boot_facility_2 ...] # Should-Stop: boot_facility_1 [ boot_facility_2 ...] # Default-Start: run_level_1 [ run_level_2 ...] # Default-Stop: run_level_1 [ run_level_2 ...] # Short-Description: single_line_description # Description: multiline_description ### END INIT INFO
Estas palabras clave que vemos aquí tienen el siguiente significado:
-
Provides
define los nombres de los servicios que proporciona el script. Suele tratarse de el nombre de un demonio. Si más de un paquete pueden proporcionar el mismo servicio (por ejemplo, los paquetessendmail
ypostfix
, o tambiéndhcpcd
ydhclient
), entonces los scripts de arranque de ambos paquetes deben proporcionar también nombres coincidentes. -
Required-Start
define qué demonios deben estar disponibles para poder iniciar y arrancar nuestro servicio. El sistema init es el responsable de asegurar que estos servicios estén arrancados de antemano. -
Should-Start
es un campo opcional. Su función es similar aRequired-Start
, pero no conlleva una dependencia estricta. Si un servicio listado aquí no está instalado, o no se arranca de forma automática, simplemente se ignora. -
Required-Stop
define los servicios que deben estar todavía disponibles durante el apagado de nuestro servicio. Nuevamente es tarea del sistema init el asegurarse de que se encuentren aún en ejecución para que nuestro script pueda detenerse de forma correcta.
Actualmente, openSUSE ignora esta cabecera, ya que el script de arranque de SUSE usa un esquema de enlace distinto (míralo en la página man init.d(7)
).
-
Should-Stop
es un campo opcional. Su función es similar aRequired-Stop
, pero no conlleva una dependencia estricta. Si un servicio de los que se listan no está instalado, o no se arranca de forma automática, simplemente se ignora. -
Default-Start
define en qué niveles de ejecución debería arrancarse nuestro script de forma automática. Los niveles de ejecución han cambiado desde SUSE Linux 7.1. -
Default-Stop
define los niveles de ejecución en los que nuestro script debería detenerse de forma automática.
Actualmente, openSUSE ignora esta cabecera, ya que el script de arranque de SUSE usa un esquema de enlace distinto (míralo en la página man init.d(7)
).
-
Short-Description
especifica una descripción sencilla de la función del servicio, en una sola línea. Esto se muestra, por ejemplo, en el Editor de niveles de ejecución de YaST. -
Description
es una descripción más detallada de la función de nuestro servicio. Cada línea adicional debe empezar con el símbolo'#'
, seguido por carácter de tabulado, o al menos dos espacios. Esta descripción multilínea acaba cuando se encuentra la primera línea que no coincide con este patrón. Esta información también se muestra en el Editor de niveles de ejecución de YaST.
La LSB permite definir en la cabecera extensiones específicas para cada distribución. Estas extensiones tienen el prefijo X-VendorTag-
. En openSUSE están disponibles las siguientes:
-
X-SuSE-Should-Start
tiene el mismo significado queShould-Start
. Quedó obsoleta a partir de la LSB 2.0, en la que se incluyóShould-Start
. -
X-SuSE-Should-Stop
tiene el mismo significado queShould-Stop
. Quedó obsoleta desde que la LSB 2.0 incluyóShould-Stop
. -
X-UnitedLinux-Default-Enabled
define si el servicio debería habilitarse por defecto. Los valores posibles sonyes
ono
. Inicialmente, fue creada para usarse en United Linux pero puede usarse igualmente en SUSE. -
X-UnitedLinux-Should-Start
es lo mismo queX-SuSE-Should-Start
pero para United Linux. -
X-UnitedLinux-Should-Stop
es lo mismo queX-SuSE-Should-Stop
pero para United Linux.
Estados definidos por defecto
Tal como marca la LSB, openSUSE proporciona ya algunos nombres de estado por defecto. Se encuentran definidos en /etc/insserv.conf
. Hasta el momento, están definidos:
-
$local_fs
— Todos los sistemas de ficheros locales están montados. La mayoría de los servicios deberían necesitar esto. -
$remote_fs
— Todos los sistemas de ficheros remotos están montados. Como/usr
puede ser montado remotamente, muchos servicios deberían necesitar también de esto. -
$syslog
— El registro del sistema está funcionando. -
$network
— La red está activa a bajo nivel (tarjeta de red, etc.). -
$named
— Está ya disponible la resolución de nombres de hosts. -
$netdaemons
— Todos los demonios de red funcionando. Esto fue quitado en la LSB 1.2. Por ahora se encuentra disponible por un tema de compatibilidad. -
$time
— La hora del sistema ha sido configurada correctamente. -
$portmap
— El mapeador de puertos SunRPC está disponible.
Acciones
Tal como marca la LSB, todos los scripts de arranque deben saber manejar los siguientes argumentos:
-
start
— Arranca el servicio. -
stop
— Detiene el servicio. -
restart
— Detiene y arranca el servicio si ya estaba en funcionamiento. Si no lo estaba, simplemente lo arranca. -
reload
— Provoca la recarga de la configuración del servicio sin detenerlo o reiniciarlo. -
force-reload
— Provoca la recarga de la configuración del servicio si es que lo soporta. Si no, reinicia el servicio. -
status
— Muestra el estado actual del servicio.
Las acciones start
, stop
, restart
, force-reload
, y status
deben estar definidas en todos los scripts de arranque. La acción reload
es opcional.
SUSE define las siguientes acciones adicionales:
-
try-restart
— Reinicia el servicio sólo si ya estaba activo antes. Esta acción forma parte ya de la LSB (desde la 1.9). Red Hat cuenta con una acción similar. llamadacondrestart
. -
probe
— Comprueba si es necesario recargar el servicio. Dependiendo del servicio, responde "reload" o "restart", si se requiere recargar el servicio. No muestra nada si no es necsario hacer nada. Esta acción es opcional y no forma parte de la LSB (desde la versión 1.9).
Códigos de salida
La LSB define los siguientes códigos de salida para los scripts de arranque:
Código de salida |
Descripción |
---|---|
0 |
éxito |
1 |
error genérico o no especificado |
2 |
argumentos inválidos o demasiados argumentos |
3 |
acción no implementada (por ejemplo, " |
4 |
el usuario no tiene privilegios suficientes |
5 |
el programa no está instalado |
6 |
el programa no está configurado |
7 |
el programa no está arrancado |
8-99 |
reservados para usos futuros de la LSB |
100-149 |
reservados para uso de la distribución |
150-199 |
reservados para uso de la aplicación |
200-254 |
reservados |
NOTA: Arrancar un servicio ya arrancado, detener o reiniciar un servicio que no se está ejecutando, así como reiniciar mediante force-reload
(en el caso de que no esté soportada la señalización) se considera éxito.
Funciones de estado
Las funciones definidas en /etc/rc.status
ayudan a grabar, mostrar y devolver información sobre el estado actual de los scripts de arranque. Pueden instanciarse desde los scripts de esta manera:
. /etc/rc.status
Están disponibles las siguientes funciones:
rc_active
Esta función comprueba si un servicio ha sido habilitado o no (mediante symlinks). Devuelve “0”
si el servicio está habilitado en un nivel de ejecución, y devuelve “1”
en caso contrario.
rc_exit
Esta función termina un script de arranque con un código de salida apropiado, de acuerdo al estado global de rc.
rc_failed [num
]
Esta función fija los estados rc local y global con un valor determinado definido con el parámetro num
. El “1”
es el código por defecto.
rc_check
Comprueba el código de salida del último comando ($?
) y fija el estado local de rc a este valor, si el valor es distinto de “0”
. Luego fija el estado rc global a el valor del estado rc local si es distinto de “0”
. Esta función se usa internamente por otras funciones de estado rc.
rc_reset
Fija los estados rc local t global a “0”
.
rc_status [-r
] [-s
] [-u
] [-v
[num
]]
Comprueba, fija y muestra el estado rc. Por defecto no hace nada; sólo llama a rc_check. Por tanto, debe llamrse con algún parámetro que muestre el estado. Los parámetros significan lo siguiente:
-
-r
llama a rc_reset. Esta opción se puede usar junto a-v
. El comando rc_status -v -r comprueba, fija y muestra el estado actual rc. Luego se llama a rc_reset. -
-s
muestra“skipped”
y fija el estado a“3”
. Significa característica no implementada. -
-u
muestra“unused”
y fija el estado a“3”
. Significa característica no implementada. -
-v
[num
] muestra el estado actual y cambia el estado local a“0”
. Por defecto, el estado se muestra en la línea actual. El parámetronum
define que se deberían mostrarnum
líneas anteriores a la posición actual del cursor.
Instalación
openSUSE proporciona varias herramientas para administrar los scripts de arranque. La más sencilla es el comando insserv
. Por ejemplo, para cargar el script de ejemplo /etc/init.d/miscript
en los niveles de ejecución por defecto, ejecuta:
insserv /etc/init.d/miscript
Para desinstalarlo, escribe
insserv -r /etc/init.d/miscript
Otra herramienta es el Editor de niveles de ejecución de YaST. Puedes lanzarlo desde la línea de comandos mediante yast runlevel
, o abriendo YaST desde el escritorio, bajo la opción Sistema. En el modo simple, habilitar un servicio lo añade a los niveles de ejecución por defecto. En modo experto, puedes especificarlos tú mismo.
Información Adicional
Si quieres saber más, consulta las siguientes páginas man:
init(8), init.d(7), insserv(8)
O echa un vistazo a los siguientes artículos:
- Creating Custom init Scripts - Novell Cool Solutions
- Especificaciones de la Linux Standard Base
- Lista de nombres de scripts de arranque ya definidos (reservados)
- Instrucciones para el registro de nombres de scripts de la LSB
<keyword>init.d,init-script,init,initscript,insserv,script</keyword>