Carpincho/build/Deb64/etc/init.d/emalibre
2026-09-29 23:32:03 -03:00

160 lines
5.7 KiB
Bash
Executable File

#!/bin/bash
### BEGIN INIT INFO
# Provides: emalibre
# Required-Start: $remote_fs $network $syslog
# Required-Stop: $remote_fs $network $syslog
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: EMA Libre Carpincho web
### END INIT INFO
PATH=/usr/sbin:/usr/bin:/sbin:/bin
export PATH
. /lib/lsb/init-functions
appFilePath=/usr/share/emalibre
pidFile=/run/emalibre.pid
logDir=/var/log/emalibre
modeFile=/etc/emalibre_modo
foreverApp="$appFilePath/node_modules/forever/bin/forever"
# Mantener el registro de instalaciones anteriores iniciadas como root.
export HOME=/root
export FOREVER_ROOT=/root/.forever
nodeBin="$appFilePath/node_modules/node/bin/node"
export PATH="$appFilePath/node_modules/node/bin:$PATH"
fail() { echo "emalibre: $*" >&2; return 1; }
require_root() {
[ "$(id -u)" -eq 0 ] || { fail "Este comando requiere root."; return 4; }
}
check_runtime() {
[ -x "$nodeBin" ] || { fail "Falta el Node incluido en $nodeBin (Node.js >= 20)."; return 5; }
"$nodeBin" -e 'process.exit(Number(process.versions.node.split(".")[0]) >= 20 ? 0 : 1)' || {
fail "Se requiere Node.js >= 20."; return 5;
}
[ -f "$foreverApp" ] && [ -f "$appFilePath/gui_web/express.js" ] || {
fail "La instalación web está incompleta."; return 5;
}
}
node_run() { "$nodeBin" "$@" 9>&-; }
forever_cmd() { node_run "$foreverApp" "$@"; }
# Consultar el supervisor, sin confiar en archivos PID residuales.
# 0: activo; 3: detenido; 4: no se pudo consultar.
process_status() {
"$nodeBin" - "$appFilePath" <<'JS'
const root = process.argv[2];
const timer = setTimeout(() => process.exit(4), 5000);
try {
require(root + '/node_modules/forever').list(false, (err, processes) => {
clearTimeout(timer);
if (err) { console.error(err.message); process.exit(4); }
const active = (processes || []).some(p => p.uid === 'EMA_Web');
process.exit(active ? 0 : 3);
});
} catch (err) { console.error(err.message); process.exit(4); }
JS
}
start() {
local state mode
process_status; state=$?
case "$state" in
0) echo "EMA Libre ya está ejecutándose."; return 0 ;;
3) ;;
*) fail "No se pudo consultar Forever."; return "$state" ;;
esac
if [ ! -f "$modeFile" ]; then
printf 'web\n' > "$modeFile" || return 1
fi
mode=$(tr -d '[:space:]' < "$modeFile") || return 1
[ "$mode" = web ] || { fail "Modo inválido: '$mode'; se esperaba web."; return 2; }
mkdir -p "$logDir" || return 1
rm -f "$pidFile" || return 1
# Forever concatena sourceDir y script: el script debe ser relativo.
forever_cmd start --uid EMA_Web --id EMA_Web --minUptime 5000 --spinSleepTime 5000 \
--sourceDir "$appFilePath" --workingDir "$appFilePath" --pidFile "$pidFile" \
-l "$logDir/forever.log" -o "$logDir/stdout.log" -e "$logDir/stderr.log" \
-a -c "$nodeBin" "gui_web/express.js" iniciar || return $?
# Forever arranca en segundo plano: esperar a que registre el supervisor.
local attempt
for attempt in {1..10}; do
process_status; state=$?
[ "$state" -eq 0 ] && { echo "EMA Libre iniciado."; return 0; }
[ "$state" -eq 3 ] || return "$state"
sleep 1
done
fail "El supervisor no arrancó; revise $logDir."
}
stop() {
local state
process_status; state=$?
case "$state" in
0) forever_cmd stop EMA_Web || return $? ;;
3) echo "EMA Libre ya está detenido." ;;
*) fail "No se pudo consultar Forever."; return "$state" ;;
esac
process_status; state=$?
[ "$state" -eq 3 ] || { fail "No se pudo confirmar la parada."; return 1; }
rm -f "$pidFile"
}
status() {
local state
process_status; state=$?
case "$state" in
0) echo "EMA Libre: supervisor activo." ;;
3) echo "EMA Libre: detenido." ;;
*) fail "Estado desconocido; no se pudo consultar Forever." ;;
esac
return "$state"
}
set_boot() {
# El arranque del servicio es independiente del inicio del recolector.
if [ -d /run/systemd/system ]; then
systemctl "$1" emalibre
else
update-rc.d emalibre defaults && update-rc.d emalibre "$1"
fi
}
view_conf() {
printf 'Modo: '; cat "$modeFile" || return 1
if [ -d /run/systemd/system ]; then
systemctl is-enabled emalibre
else
echo 'Inicio del servicio: consultar enlaces /etc/rc[2-5].d/*emalibre'
fi
"$nodeBin" - "$appFilePath/conf/ConfiguracionGeneral.js" <<'JS'
const cfg = require(process.argv[2]).ConfGeneral;
for (const key of ['Tiempo_de_Recoleccion', 'UTC', 'SistemaMetrico', 'debug',
'debugTamanio', 'NombreEstacion', 'Modo', 'inicio_automatico', 'Audio',
'notificar_cambios', 'audioVoces', 'IP', 'Puerto', 'Ruta']) {
console.log(key + ': ' + cfg[key]);
}
JS
}
case "${1:-}" in
start|stop|restart|force-reload|status|uptime|reporte|view-conf|set-inicio-enabled|set-inicio-disable) ;;
*) echo "Uso: $0 {start|stop|restart|force-reload|status|uptime|reporte|view-conf|set-inicio-enabled|set-inicio-disable}" >&2; exit 2 ;;
esac
require_root || exit $?
check_runtime || exit $?
case "$1" in
start|stop|restart|force-reload|set-inicio-enabled|set-inicio-disable)
# Evitar arranques/paradas simultáneos. Cerrar el descriptor en Node
# impide que el daemon herede y retenga el bloqueo.
exec 9>/run/lock/emalibre.lock || exit 1
flock -w 30 9 || exit 1
;;
esac
case "$1" in
start) start ;;
stop) stop ;;
restart|force-reload) stop && start ;;
status) status ;;
uptime) forever_cmd list ;;
reporte) (cd "$appFilePath" && node_run core/reporte.js) ;;
view-conf) view_conf ;;
set-inicio-enabled) set_boot enable ;;
set-inicio-disable) set_boot disable ;;
esac
exit $?