release v1.0
This commit is contained in:
@@ -0,0 +1,44 @@
|
||||
#!/usr/bin/env bash
|
||||
# mariadb_clean_stop.sh - Cierre limipio del contenedor de MariaDB en una maquina
|
||||
|
||||
# CONFIGURACION ---------------------------------------------------------------
|
||||
set -uo pipefail
|
||||
# -u -> si no existe una variable devuelve error en vez de tratarla como cadnea vacia
|
||||
# -o pipefail -> devuelve los errores de cualquier pipe no solo del ultimo
|
||||
|
||||
# VARIABLES
|
||||
CONTAINER="mariadb"
|
||||
GRACE=60
|
||||
LOG="/var/log/safe-shutdown.log"
|
||||
# -----------------------------------------------------------------------------
|
||||
# funcion para escribir en el log
|
||||
log() { echo "$(date -Is) [mariadb-safe-stop] $*" | tee -a "$LOG"; }
|
||||
|
||||
# PROGRAMA --------------------------------------------------------------------
|
||||
log "inicio"
|
||||
|
||||
# Comprobacion de que el contenedor esta corriendo
|
||||
# Lista los nombres de los contenedores activos y busca exactamente el nombre de $CONTAINER
|
||||
# Si no lo encuentra escribe un aviso en el log y sale con 0
|
||||
if ! docker ps --format '{{.Names}}' | grep -qx "$CONTAINER"; then
|
||||
log "AVISO: el contenedor '$CONTAINER' no esta corriendo. Nada que hacer."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Parada del contenedor
|
||||
log "parando contenedor '$CONTAINER' (tiempo de gracia: ${GRACE}s)..."
|
||||
if docker stop -t "$GRACE" "$CONTAINER" >/dev/null; then
|
||||
log "OK: Contenedor parado con exito"
|
||||
else
|
||||
log "ERROR: docker stop falló"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Verificacion del estado del contenedor
|
||||
if docker ps --format '{{.Names}}' | grep -qx "$CONTAINER"; then
|
||||
log "ERROR: '$CONTAINER' sigue activo despues del stop"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
log "contenedor '$CONTAINER' detenido correctamente"
|
||||
log "fin"
|
||||
@@ -0,0 +1,39 @@
|
||||
#!/usr/bin/env bash
|
||||
# orchestrate-shutdown.sh — secuencia completa de apagado ordenado.
|
||||
# Lo dispara el watcher al detectar un fichero de señal.
|
||||
# Orden:
|
||||
# 1. HA apaga los Shellys de la instalacion
|
||||
# 2. HA crea el fichero de señal
|
||||
# 3. Se inicia este script
|
||||
# 3.1. Apagado de raspis y/o equipos de servicio
|
||||
# 3.2. Parado de MariaDB
|
||||
|
||||
set -uo pipefail
|
||||
|
||||
# CONFIGURACION----------------------------------------------------------------
|
||||
LOG="/var/log/safe-shutdown.log"
|
||||
APAGADO_NODOS="/usr/local/sbin/service-nodes-shutdown.sh"
|
||||
APAGADO_BDD="/usr/local/sbin/mariadb-shutdown.sh"
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
log() { echo "$(date -Is) [orchestrate] $*" | tee -a "$LOG"; }
|
||||
|
||||
log "===== SECUENCIA DE APAGADO INICIADA ====="
|
||||
|
||||
# 1. Apagar la(s) raspi(s) de servicio por SSH (espera a que hagan halt).
|
||||
log "paso 1: apagando raspis de servicio..."
|
||||
if "$APAGADO_NODOS"; then
|
||||
log "paso 1 ok"
|
||||
else
|
||||
log "paso 1: aviso, el script para el apagado de los nodos devolvio error"
|
||||
fi
|
||||
|
||||
# 2. Cerrar la base de datos limpiamente.
|
||||
log "paso 2: cerrando la base de datos..."
|
||||
if "$APAGADO_BDD"; then
|
||||
log "paso 2 OK"
|
||||
else
|
||||
log "paso 2: ERROR al cerrar la BD"
|
||||
fi
|
||||
|
||||
log "===== SECUENCIA DE APAGADO COMPLETADA ====="
|
||||
@@ -0,0 +1,56 @@
|
||||
#!/usr/bin/env bash
|
||||
# orchestrate-startup.sh — secuencia de arranque tras un rebote (corre en el HOST).
|
||||
# Lo dispara el watcher al detectar el fichero de señal 'encender'.
|
||||
# Orden INVERSO al apagado: primero la BD (para que esté lista antes de que
|
||||
# los escritores vuelvan), luego HA reenciende Shelly/nodos por su cuenta.
|
||||
#
|
||||
# NOTA: el reencendido de los Shelly (Arduinos y raspi de servicio) lo hace la
|
||||
# automatización de HA. Este script solo se ocupa de lo que vive en el host:
|
||||
# arrancar el contenedor de la base de datos y confirmar que responde.
|
||||
|
||||
set -uo pipefail
|
||||
|
||||
# CONFIG ----------------------------------------------------------------------
|
||||
CONTAINER="mariadb"
|
||||
LOG="/var/log/safe-shutdown.log"
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
log() { echo "$(date -Is) [orchestrate-startup] $*" | tee -a "$LOG"; }
|
||||
|
||||
log "===== SECUENCIA DE ARRANQUE INICIADA ====="
|
||||
|
||||
# ¿Ya está corriendo? (idempotente: por si la señal llega dos veces)
|
||||
if docker ps --format '{{.Names}}' | grep -qx "$CONTAINER"; then
|
||||
log "el contenedor '$CONTAINER' ya está corriendo. Nada que hacer."
|
||||
log "===== SECUENCIA DE ARRANQUE COMPLETADA ====="
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# 1. Arrancar el contenedor de la BD.
|
||||
log "arrancando contenedor '$CONTAINER'..."
|
||||
if docker start "$CONTAINER" >/dev/null; then
|
||||
log "docker start devolvió OK"
|
||||
else
|
||||
log "ERROR: docker start falló"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 2. Esperar a que MariaDB acepte conexiones (no basta con que el contenedor
|
||||
# esté 'Up': el servidor tarda unos segundos en estar listo).
|
||||
log "esperando a que MariaDB acepte conexiones..."
|
||||
ready=0
|
||||
for i in {1..30}; do
|
||||
if docker exec "$CONTAINER" mariadb-admin ping --silent &>/dev/null; then
|
||||
ready=1
|
||||
log "MariaDB responde (tras ${i}s)"
|
||||
break
|
||||
fi
|
||||
sleep 1
|
||||
done
|
||||
|
||||
if [[ "$ready" -eq 0 ]]; then
|
||||
log "ERROR: MariaDB no respondió tras 30s"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
log "===== SECUENCIA DE ARRANQUE COMPLETADA ====="
|
||||
@@ -0,0 +1,70 @@
|
||||
#!/usr/bin/env bash
|
||||
# total-shutdown.sh — FASE 2: apagado TOTAL de la raspi principal.
|
||||
# Corre en el HOST. Cierra BD + HA y finalmente apaga la propia máquina.
|
||||
#
|
||||
# ATENCIÓN: la última acción es 'poweroff'. Tras ejecutarse, la raspi se apaga.
|
||||
# Solo volverá a encenderse cuando reciba de nuevo alimentación (corte físico +
|
||||
# retorno de tensión). Si la apagas con corriente aún disponible, NO arrancará
|
||||
# sola: requerirá corte/retorno de alimentación o encendido manual.
|
||||
#
|
||||
# Este script asume que la FASE 1 (Arduinos + raspi de servicio) ya se ejecutó.
|
||||
# Pensado para dispararse solo cuando el SoC cruza el segundo umbral (más bajo)
|
||||
# y la red sigue sin volver.
|
||||
|
||||
set -uo pipefail
|
||||
|
||||
# CONFIG ----------------------------------------------------------------------
|
||||
DB_CONTAINER="mariadb"
|
||||
HA_CONTAINER="homeassistant"
|
||||
APAGADO_NODOS="/usr/local/sbin/service-nodes-shutdown.sh"
|
||||
APAGADO_BDD="/usr/local/sbin/mariadb-shutdown.sh"
|
||||
LOG="/var/log/safe-shutdown.log"
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
log() { echo "$(date -Is) [full-shutdown] $*" | tee -a "$LOG"; }
|
||||
|
||||
log "===== FASE 2: APAGADO TOTAL INICIADO ====="
|
||||
# 1. Comprobar que los nodos de servicio estan apagados
|
||||
log "paso 1: asegurando el apagado de nodos de servicio..."
|
||||
if "$APAGADO_NODOS"; then
|
||||
log "paso 1: OK, todos los nodos apagados"
|
||||
else
|
||||
log "paso 1: ERROR, el script de apagado de nodos fallo"
|
||||
fi
|
||||
|
||||
# 2. Cerrar la BD limpiamente (si sigue corriendo). Reutiliza el script probado.
|
||||
if docker ps --format '{{.Names}}' | grep -qx "$DB_CONTAINER"; then
|
||||
log "paso 2: la BD sigue corriendo, cerrándola..."
|
||||
if "$APAGADO_BDD"; then
|
||||
log "paso 2 OK"
|
||||
else
|
||||
log "paso 2: AVISO, el cierre de BD devolvió error (continuamos igualmente)"
|
||||
fi
|
||||
else
|
||||
log "paso 2: la BD ya estaba parada (cerrada en fase 1). Saltando."
|
||||
fi
|
||||
|
||||
# 3. Parar Home Assistant limpiamente.
|
||||
if docker ps --format '{{.Names}}' | grep -qx "$HA_CONTAINER"; then
|
||||
log "paso 3: parando Home Assistant..."
|
||||
if docker stop -t 30 "$HA_CONTAINER" >/dev/null; then
|
||||
log "paso 3 OK"
|
||||
else
|
||||
log "paso 3: AVISO, docker stop de HA devolvió error (continuamos)"
|
||||
fi
|
||||
else
|
||||
log "paso 3: Home Assistant no estaba corriendo. Saltando."
|
||||
fi
|
||||
|
||||
# 4. Forzar que todo baje a disco antes de cortar.
|
||||
log "paso 4: sincronizando discos (sync)..."
|
||||
sync
|
||||
sleep 2
|
||||
sync
|
||||
log "paso 4 OK"
|
||||
|
||||
# 5. Apagar la propia máquina. ESTA ES LA ÚLTIMA LÍNEA QUE SE EJECUTA.
|
||||
log "paso 5: apagando la raspi principal. Hasta luego."
|
||||
log "===== FASE 2: APAGADO TOTAL COMPLETADO (poweroff a continuación) ====="
|
||||
sync
|
||||
systemctl poweroff
|
||||
@@ -0,0 +1,58 @@
|
||||
#!/usr/bin/env bash
|
||||
# service-nodes-shutdown.sh - Apagado de la(s) raspi(s) de servicio por SSH de
|
||||
# forma segura. Se ejecuta en la raspi principal. Ordena el poweroff y espera
|
||||
# a que deje de hacer ping antes de continuar. Despues corta la alimentacion
|
||||
# fisica a traves del relé correspondiente.
|
||||
|
||||
# REQUISITOS:
|
||||
# - Claves SSH sin passphrase en /root/.ssh/id_shutdown autorizada en cada nodo
|
||||
# - Regla sudoers NOPASSWD para /usr/sbin/poweroff en cada nodo
|
||||
|
||||
set -uo pipefail
|
||||
|
||||
# CONFIGURACION ---------------------------------------------------------------
|
||||
NODES=(
|
||||
"pi@192.168.1.219|sudo /usr/sbin/poweroff" # Raspi Dinamica
|
||||
"root@192.168.1.50|/sbin/poweroff" # NVR
|
||||
)
|
||||
SSH_KEY="/root/.ssh/id_shutdown"
|
||||
POWEROFF_CMD="sudo /usr/sbin/poweroff"
|
||||
TIMEOUT_HALT=60 # Timeout para el apagado
|
||||
LOG="/var/log/safe-shutdown.log"
|
||||
SSH_OPTS="-i $SSH_KEY -o BatchMode=yes -o ConnectTimeout=5 -o StrictHostKeyChecking=accept-new"
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
log() { echo "$(date -Is) [service-nodes-shutdown] $*" | tee -a "$LOG"; }
|
||||
|
||||
log "inicio (${#NODES[@]} nodo/s)"
|
||||
|
||||
for entry in "${NODES[@]}"; do
|
||||
host_user="${entry%%|*}"
|
||||
host="${host_user#*@}" # extrae la IP/host del NODE
|
||||
cmd="${entry#*|}"
|
||||
log "apagando $host_user ..."
|
||||
|
||||
# Ordenar poweroff por ssh
|
||||
if ssh $SSH_OPTS "$host_user" "$cmd"; then
|
||||
log "$entry: orden de poweroff enviada"
|
||||
else # Si falla avisamos y seguimos (puede no ser un error real)
|
||||
log "$entry: AVISO, el SSH devolvio error"
|
||||
fi
|
||||
|
||||
# Esperamos la NO respuesta de ping
|
||||
halted=0
|
||||
for ((i=1; i<TIMEOUT_HALT; i++)); do
|
||||
if ! ping -c1 -W1 "$host" &>/dev/null; then
|
||||
log "$host: apagado confirmado (dejo de responder tras ${i}s)"
|
||||
halted=1
|
||||
break
|
||||
fi
|
||||
sleep 1
|
||||
done
|
||||
|
||||
if [[ "$halted" -eq 0 ]]; then
|
||||
log "$host: AVISO, sigue respondiendo tras ${TIMEOUT_HALT}s (apagado no confirmado)"
|
||||
fi
|
||||
done
|
||||
|
||||
log "fin"
|
||||
@@ -0,0 +1,40 @@
|
||||
#!/usr/bin/env bash
|
||||
set -uo pipefail
|
||||
|
||||
# CONFIGURACION ---------------------------------------------------------------
|
||||
SIGNAL_DIR="/opt/shutdown-signal"
|
||||
SHUTDOWN_ORCHESTRATOR="/usr/local/sbin/orchestrate-shutdown.sh"
|
||||
TOTAL_SHUTDOWN_ORCHESTRATOR="/usr/local/sbin/orchestrate-total-shutdown.sh"
|
||||
STARTUP_ORCHESTRATOR="/usr/local/sbin/orchestrate-startup.sh"
|
||||
LOG="/var/log/safe-shutdown.log"
|
||||
|
||||
# PROGRAMA --------------------------------------------------------------------
|
||||
log() { echo "$(date -Is) [watcher] $*" | tee -a "$LOG"; }
|
||||
|
||||
log "watcher iniciado, vigilando $SIGNAL_DIR/"
|
||||
|
||||
while true; do
|
||||
inotifywait -q -e create -e moved_to "$SIGNAL_DIR" |
|
||||
while read -r dir event file; do
|
||||
case "$file" in
|
||||
apagar)
|
||||
log "señal detectada ($file). Lanzando secuencia de apagado."
|
||||
"$SHUTDOWN_ORCHESTRATOR"
|
||||
rm -f "$SIGNAL_DIR/apagar"
|
||||
log "señal consumida y borrada."
|
||||
;;
|
||||
encender)
|
||||
log "señal detectada ($file). Lanzando secuencia de encendido."
|
||||
"$STARTUP_ORCHESTRATOR"
|
||||
rm -f "$SIGNAL_DIR/encender"
|
||||
log "señal consumida y borrada."
|
||||
;;
|
||||
apagado_total)
|
||||
log "señal detectada ($file). Lanzando secuencia de apagado TOTAL."
|
||||
"$TOTAL_SHUTDOWN_ORCHESTRATOR"
|
||||
rm -f "$SIGNAL_DIR/apagado_total"
|
||||
log "señal consumida y borrada."
|
||||
;;
|
||||
esac
|
||||
done
|
||||
done
|
||||
Reference in New Issue
Block a user