Creación de scripts init personalizados con OpenRC

OpenRC proporciona una forma ligera de gestionar servicios en Gentoo y otras distribuciones. A través de start-stop-daemon se puede arrancar, detener y recargar aplicaciones sin que el propio programa implemente la lógica de demonio. A continuación se describe paso a paso cómo crear un script init para una aplicación cualquiera.

Estructura base del script

Cree el archivo en /etc/init.d con su editor preferido:

cd /etc/init.d
vim mi-servicio

Una plantilla mínima para OpenRC tiene este aspecto:

#!/sbin/openrc-run
# Copyright 1999-2013 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2

depend() {
}

start() {
}

stop() {
}

Es importante que cada función tenga un cuerpo, aunque sea vacío con un simple return 0; de lo contrario, el demonio de inicio podría rechazar el script.

Definición de variables

Para evitar repetir rutas y nombres, conviene declarar variables al principio del archivo:

APP_DIR="/opt/mi-servicio"
APP_BIN="${APP_DIR}/mi-servicio"
PID_FILE="/run/mi-servicio.pid"
APP_USER="appserver"

Dependencias

La función depend() indica qué subsistemas deben estar disponibles antes de arrancar el servicio. Por ejemplo, una aplicación web normalmente necesita red y sistemas de archivos locales:

depend() {
    need net
    need localmount
}

Además de need, se pueden emplear:

  • use: dependencia blanda; el servicio aprovecha el recurso si existe, pero no es obligatorio.
  • before: arranca antes que otro servicio.
  • after: arranca después de otro servicio.

Inicio del servicio

La función start() utiliza ebegin y eend para mostrar mensajes formateados en los registros adecuados:

start() {
    ebegin "Iniciando mi-servicio"
    start-stop-daemon --background --start \
        --exec "${APP_BIN}" \
        --make-pidfile --pidfile "${PID_FILE}" \
        --user "${APP_USER}"
    eend $?
}

Con --background, start-stop-daemon se encarga de convertir la aplicación en demonio, por lo que no es necesario hacerlo en el código de la aplicación.

Pasar argumentos al programa

Si la aplicación necesita opciones, se colocan tras un doble guion al final de la línea de comando:

start() {
    ebegin "Iniciando mi-servicio"
    start-stop-daemon --background --start \
        --exec "${APP_BIN}" \
        --make-pidfile --pidfile "${PID_FILE}" \
        --user "${APP_USER}" \
        -- --puerto 8080 --modo produccion
    eend $?
}

Variables de entorno

Para definir varias variables de entorno, resulta más limpio usar el comando env antes del ejecutable:

start() {
    ebegin "Iniciando mi-servicio"
    start-stop-daemon --background --start \
        --exec env \
            DB_HOST=db.example.com \
            CACHE_HOST=cache.example.com \
            LOG_LEVEL=info \
        -- "${APP_BIN}" \
        --make-pidfile --pidfile "${PID_FILE}" \
        --user "${APP_USER}" \
        -- --puerto 8080
    eend $?
}

Nota: cuando el ejecutable se construye con env, los argumentos de start-stop-daemon deben colocarse después del binario real, prestando atención a la posición de --make-pidfile y --user según la sintaxis del daemon.

Espera al arranque

Si la aplicación tarda en estar operativa porque conecta a bases de datos o colas de mensajes, se puede indicar a start-stop-daemon que espere unos milisegundos antes de considerar el inicio exitoso:

start() {
    ebegin "Iniciando mi-servicio"
    start-stop-daemon --wait 5000 --background --start \
        --exec "${APP_BIN}" \
        --make-pidfile --pidfile "${PID_FILE}" \
        --user "${APP_USER}" \
        -- --puerto 8080
    eend $?
}

Parada del servicio

La función stop() se invoca tanto al detener como al reiniciar el servicio. Especificar el archivo PID mejora la precisión y el rendimiento:

stop() {
    ebegin "Deteniendo mi-servicio"
    start-stop-daemon --stop --exec "${APP_BIN}" \
        --pidfile "${PID_FILE}"
    eend $?
}

Recarga mediante señales

OpenRC permite definir funciones adicionales. Por ejemplo, para recargar la configuración enviando SIGHUP:

reload() {
    ebegin "Recargando mi-servicio"
    start-stop-daemon --exec "${APP_BIN}" \
        --pidfile "${PID_FILE}" \
        --signal 1
    eend $?
}

Habilitación y uso

Después de guardar el script, se le asignan permisos de ejecución:

chmod +x /etc/init.d/mi-servicio

Para arrancar, detener o recargar manualmente:

rc-service mi-servicio start
rc-service mi-servicio stop
rc-service mi-servicio restart
rc-service mi-servicio reload

Para que el servicio se inicie automáticamente en el runlevel por defecto:

rc-update add mi-servicio default

Se puede verificar el estado con:

rc-status

Permisos sudo para despliegues automatizados

Si un usuario no privilegiado debe poder gestionar el servicio desde un script de despliegue, se puede añadir una regla en /etc/sudoers:

appserver ALL=(ALL) NOPASSWD: /etc/init.d/mi-servicio start
appserver ALL=(ALL) NOPASSWD: /etc/init.d/mi-servicio stop
appserver ALL=(ALL) NOPASSWD: /etc/init.d/mi-servicio restart
appserver ALL=(ALL) NOPASSWD: /etc/init.d/mi-servicio reload

Utilizar start-stop-daemon junto con OpenRC permite externalizar la gestión de demonios, archivos PID y runlevels, reduciendo la complejidad de la propia aplicación y aprovechando las herramientas que ya ofrece el sistema operativo.

Etiquetas: OpenRC start-stop-daemon Gentoo init scripts rc-service

Publicado el 7-13 17:10