- Watchdog (30s) : vérifie backend, caméra, chromium, tue les orphelins, reboot auto après 10 échecs consécutifs (~5min sans service) - kiosk-session.sh : tue les backends orphelins au démarrage, trap EXIT pour cleanup quand le kiosk est tué - camera.py : force release USB avec timeout 2s quand connecter() échoue - main.py : uvicorn.run(app) au lieu de string pour éviter double import Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
102 lines
3.4 KiB
Bash
102 lines
3.4 KiB
Bash
#!/bin/bash
|
||
# Watchdog photobooth — tourne toutes les 30s via systemd timer
|
||
# Vérifie backend, camera, chromium. Escalade jusqu'au reboot si nécessaire.
|
||
|
||
HEALTH_URL="http://localhost/api/health"
|
||
STATE_FILE="/tmp/photobooth-watchdog-failures"
|
||
MAX_FAILURES=10 # 10 échecs × 30s = 5 min avant reboot
|
||
LOG_TAG="photobooth-watchdog"
|
||
|
||
log() { logger -t "$LOG_TAG" "$1"; }
|
||
|
||
# Compteur d'échecs persistant
|
||
failures=$(cat "$STATE_FILE" 2>/dev/null || echo 0)
|
||
|
||
# --- 1. Tuer les backends orphelins (ppid=1, pas rattachés au kiosk) ---
|
||
while IFS= read -r line; do
|
||
pid=$(echo "$line" | awk '{print $1}')
|
||
ppid=$(echo "$line" | awk '{print $2}')
|
||
if [ "$ppid" = "1" ]; then
|
||
log "Backend orphelin détecté (pid=$pid), kill"
|
||
kill -9 "$pid" 2>/dev/null
|
||
fi
|
||
done < <(ps -eo pid,ppid,args | grep 'python.*backend.main' | grep -v grep)
|
||
|
||
# --- 2. Vérifier que le backend répond ---
|
||
health=$(curl -sf --max-time 5 "$HEALTH_URL" 2>/dev/null)
|
||
if [ -z "$health" ]; then
|
||
log "Backend ne répond pas (échec $((failures+1))/$MAX_FAILURES)"
|
||
# Vérifier si un process backend existe
|
||
if ! pgrep -f 'python.*backend.main' > /dev/null 2>&1; then
|
||
log "Aucun backend en cours — le kiosk devrait le relancer"
|
||
fi
|
||
failures=$((failures + 1))
|
||
echo "$failures" > "$STATE_FILE"
|
||
|
||
if [ "$failures" -ge "$MAX_FAILURES" ]; then
|
||
log "REBOOT: $MAX_FAILURES échecs consécutifs, redémarrage système"
|
||
echo 0 > "$STATE_FILE"
|
||
/usr/sbin/reboot
|
||
fi
|
||
exit 0
|
||
fi
|
||
|
||
# Backend répond — extraire l'état caméra
|
||
camera=$(echo "$health" | python3 -c 'import sys,json; print(json.load(sys.stdin).get("camera",""))' 2>/dev/null)
|
||
clients=$(echo "$health" | python3 -c 'import sys,json; print(json.load(sys.stdin).get("clients",0))' 2>/dev/null)
|
||
|
||
# --- 3. Vérifier la caméra ---
|
||
if [ "$camera" = "disconnected" ] || [ "$camera" = "erreur" ]; then
|
||
log "Caméra déconnectée, tentative USB reset Canon"
|
||
|
||
# USB ioctl reset du Canon (vendor 04a9)
|
||
python3 -c '
|
||
import fcntl, glob, os
|
||
for f in glob.glob("/sys/bus/usb/devices/*/idVendor"):
|
||
if open(f).read().strip() == "04a9":
|
||
d = os.path.dirname(f)
|
||
bus = open(d + "/busnum").read().strip().zfill(3)
|
||
dev = open(d + "/devnum").read().strip().zfill(3)
|
||
path = f"/dev/bus/usb/{bus}/{dev}"
|
||
with open(path, "wb") as fh:
|
||
fcntl.ioctl(fh, 0x5514, 0)
|
||
print(f"USB reset: {path}")
|
||
' 2>/dev/null
|
||
|
||
# Si le Canon n'est même pas sur le bus USB
|
||
if ! lsusb 2>/dev/null | grep -q "04a9"; then
|
||
log "Canon absent du bus USB"
|
||
failures=$((failures + 1))
|
||
else
|
||
failures=$((failures + 1))
|
||
fi
|
||
|
||
echo "$failures" > "$STATE_FILE"
|
||
|
||
if [ "$failures" -ge "$MAX_FAILURES" ]; then
|
||
log "REBOOT: caméra injoignable depuis $MAX_FAILURES cycles"
|
||
echo 0 > "$STATE_FILE"
|
||
/usr/sbin/reboot
|
||
fi
|
||
exit 0
|
||
fi
|
||
|
||
# --- 4. Vérifier Chromium ---
|
||
if ! pgrep -f chromium > /dev/null 2>&1; then
|
||
log "Chromium ne tourne pas — restart lightdm"
|
||
systemctl restart lightdm
|
||
failures=$((failures + 1))
|
||
echo "$failures" > "$STATE_FILE"
|
||
exit 0
|
||
fi
|
||
|
||
# --- 5. Tuer gvfsd-gphoto2 s'il revient ---
|
||
pkill -f gvfsd-gphoto2 2>/dev/null
|
||
pkill -f gvfs-gphoto2-volume-monitor 2>/dev/null
|
||
|
||
# --- Tout va bien : reset compteur ---
|
||
if [ "$failures" -gt 0 ]; then
|
||
log "Système OK (camera=$camera, clients=$clients) — compteur remis à 0"
|
||
fi
|
||
echo 0 > "$STATE_FILE"
|