server: add watchdog fail-safes
This commit is contained in:
parent
4e96c271ed
commit
67cddf6a99
31
scripts/daemon/lesavka-hw-watchdog.py
Normal file
31
scripts/daemon/lesavka-hw-watchdog.py
Normal file
@ -0,0 +1,31 @@
|
||||
#!/usr/bin/env python3
|
||||
import os
|
||||
import signal
|
||||
import time
|
||||
|
||||
path = os.environ.get("LESAVKA_WATCHDOG_DEV", "/dev/watchdog")
|
||||
interval = float(os.environ.get("LESAVKA_WATCHDOG_INTERVAL", "5"))
|
||||
|
||||
fd = os.open(path, os.O_WRONLY)
|
||||
|
||||
running = True
|
||||
|
||||
|
||||
def handle(_sig, _frame):
|
||||
global running
|
||||
running = False
|
||||
|
||||
|
||||
signal.signal(signal.SIGTERM, handle)
|
||||
signal.signal(signal.SIGINT, handle)
|
||||
|
||||
try:
|
||||
while running:
|
||||
os.write(fd, b"\0")
|
||||
time.sleep(interval)
|
||||
finally:
|
||||
try:
|
||||
os.write(fd, b"V")
|
||||
except Exception:
|
||||
pass
|
||||
os.close(fd)
|
||||
13
scripts/daemon/lesavka-hw-watchdog.service
Normal file
13
scripts/daemon/lesavka-hw-watchdog.service
Normal file
@ -0,0 +1,13 @@
|
||||
[Unit]
|
||||
Description=Lesavka hardware watchdog
|
||||
ConditionPathExists=/dev/watchdog
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
ExecStart=/usr/local/bin/lesavka-hw-watchdog.py
|
||||
Restart=always
|
||||
RestartSec=2
|
||||
KillMode=process
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
10
scripts/daemon/lesavka-watchdog.service
Normal file
10
scripts/daemon/lesavka-watchdog.service
Normal file
@ -0,0 +1,10 @@
|
||||
[Unit]
|
||||
Description=Lesavka reboot watchdog
|
||||
ConditionPathExists=!/etc/lesavka/no-reboot
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
ExecStart=/usr/local/bin/lesavka-watchdog.sh
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
23
scripts/daemon/lesavka-watchdog.sh
Normal file
23
scripts/daemon/lesavka-watchdog.sh
Normal file
@ -0,0 +1,23 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
HEARTBEAT=/etc/lesavka/watchdog.touch
|
||||
MAX_AGE_SEC=${LESAVKA_WATCHDOG_MAX_AGE:-840}
|
||||
|
||||
if [[ -f /etc/lesavka/no-reboot ]]; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
now=$(date +%s)
|
||||
if [[ ! -f "$HEARTBEAT" ]]; then
|
||||
logger -t lesavka-watchdog "no heartbeat file; rebooting"
|
||||
systemctl --no-wall reboot
|
||||
exit 0
|
||||
fi
|
||||
|
||||
mtime=$(stat -c %Y "$HEARTBEAT" 2>/dev/null || echo 0)
|
||||
age=$((now - mtime))
|
||||
if (( age > MAX_AGE_SEC )); then
|
||||
logger -t lesavka-watchdog "heartbeat stale (${age}s); rebooting"
|
||||
systemctl --no-wall reboot
|
||||
fi
|
||||
11
scripts/daemon/lesavka-watchdog.timer
Normal file
11
scripts/daemon/lesavka-watchdog.timer
Normal file
@ -0,0 +1,11 @@
|
||||
[Unit]
|
||||
Description=Lesavka reboot watchdog timer
|
||||
|
||||
[Timer]
|
||||
OnBootSec=15min
|
||||
OnUnitActiveSec=15min
|
||||
AccuracySec=30s
|
||||
Persistent=true
|
||||
|
||||
[Install]
|
||||
WantedBy=timers.target
|
||||
@ -157,6 +157,8 @@ sudo install -Dm755 "$SRC_DIR/server/target/release/lesavka-server" /usr/local/b
|
||||
sudo install -Dm755 "$SRC_DIR/server/target/release/lesavka-uvc" /usr/local/bin/lesavka-uvc
|
||||
sudo install -Dm755 "$SRC_DIR/scripts/daemon/lesavka-core.sh" /usr/local/bin/lesavka-core.sh
|
||||
sudo install -Dm755 "$SRC_DIR/scripts/daemon/lesavka-uvc.sh" /usr/local/bin/lesavka-uvc.sh
|
||||
sudo install -Dm755 "$SRC_DIR/scripts/daemon/lesavka-watchdog.sh" /usr/local/bin/lesavka-watchdog.sh
|
||||
sudo install -Dm755 "$SRC_DIR/scripts/daemon/lesavka-hw-watchdog.py" /usr/local/bin/lesavka-hw-watchdog.py
|
||||
|
||||
echo "==> 6a. Systemd units - lesavka-core"
|
||||
cat <<'UNIT' | sudo tee /etc/systemd/system/lesavka-core.service >/dev/null
|
||||
@ -243,6 +245,57 @@ User=root
|
||||
WantedBy=multi-user.target
|
||||
UNIT
|
||||
|
||||
echo "==> 6d. Systemd units - watchdogs"
|
||||
cat <<'UNIT' | sudo tee /etc/systemd/system/lesavka-watchdog.service >/dev/null
|
||||
[Unit]
|
||||
Description=Lesavka reboot watchdog
|
||||
ConditionPathExists=!/etc/lesavka/no-reboot
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
ExecStart=/usr/local/bin/lesavka-watchdog.sh
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
UNIT
|
||||
|
||||
cat <<'UNIT' | sudo tee /etc/systemd/system/lesavka-watchdog.timer >/dev/null
|
||||
[Unit]
|
||||
Description=Lesavka reboot watchdog timer
|
||||
|
||||
[Timer]
|
||||
OnBootSec=15min
|
||||
OnUnitActiveSec=15min
|
||||
AccuracySec=30s
|
||||
Persistent=true
|
||||
|
||||
[Install]
|
||||
WantedBy=timers.target
|
||||
UNIT
|
||||
|
||||
cat <<'UNIT' | sudo tee /etc/systemd/system/lesavka-hw-watchdog.service >/dev/null
|
||||
[Unit]
|
||||
Description=Lesavka hardware watchdog
|
||||
ConditionPathExists=/dev/watchdog
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
ExecStart=/usr/local/bin/lesavka-hw-watchdog.py
|
||||
Restart=always
|
||||
RestartSec=2
|
||||
KillMode=process
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
UNIT
|
||||
|
||||
sudo install -d /etc/lesavka
|
||||
sudo touch /etc/lesavka/watchdog.touch
|
||||
|
||||
sudo systemctl daemon-reload
|
||||
sudo systemctl enable --now lesavka-hw-watchdog
|
||||
sudo systemctl enable --now lesavka-watchdog.timer
|
||||
|
||||
if [[ -n ${LESAVKA_ALLOW_GADGET_RESET:-} ]] || ! is_attached_state "$UDC_STATE"; then
|
||||
sudo systemctl restart lesavka-uvc
|
||||
echo "✅ lesavka-uvc installed and restarted..."
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user