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.