Nachtrag 22.07.26: nut-watchdog Script gefixt, ich hatte ein “/” vergessen und noch etwas ergänzt. Ich lade alle Scripte in Zukunft bei Github hoch. Man findet die aktuellste Version hier
Ich habe für diesen Beitrag teilweise einem älteren Beitrag aus dem alten Discordchannel gefleddert. Daher liest es sich evtl etwas seltsam, entscheidend ist jedoch der Inhalt und die Lösung am Ende.
Hintergrund war, dass der NUT Server, ohne erkennbares Muster, immer wieder die USB Verbindung zur USV verloren hatte. Leider hatte ich den NUT Dienst selbst bisher nicht auf durchgehende Funktionstüchtigkeit überwacht….
Es kam in den PVE Logs diese Fehlermeldung
usbhid-ups[1558]: libusb1: Could not open any HID devices: insufficient permissions on everything
die sich fortlaufend wiederholt. Interessanterweise ließ sich das Problem mit einem simplen
systemctl restart nut-driver@usv-giesing.service
beheben. Der Fehler wurde ein paar Mal in ähnlicher Form im Proxmoxforum berichtet. Er scheint spontan gekommen und wieder verschwunden zu sein. Evtl ist eines der Kernelupdates schuld, es hat ein Jahr ohne Probleme funktioniert und bereits einen Stromausfall erfolgreich abgefangen.
Jemand im Proxmoxforum hatte den entscheidenden Hinweis:
@elvito das insufficient permissions on everything ist meist gar kein Rechteproblem, sondern ein USB-Reenumerations-Ding. Die USV meldet sich (oft nach nem Glitch am USB) mit neuer Bus-/Device-Nummer wieder an, der usbhid-ups hängt aber noch am alten Handle und kommt nicht von selbst zurück. Ein Restart vom nut-driver hilft da sofort. Manchmal kann man den Treiber per Vendor:Product-ID statt port=auto binden, aber ganz weg kriegt man das nicht immer.
Ich hatte zu Beginn der Probleme mit der USV, die Software Nutwatch in einer VM installiert. Es hat einen gewissen Charme die NUT/USV Überwachung in einer Backup- und Clonebaren VM zu haben, zum Preis des anfallenden Ressourcenverbrauchs. Das hat gut funktioniert, wer Nutwatch auch als NUT Server einsetzen will, sollte unbedingt einen API Key setzen, sonst könnte diese VM zu einem hochgefährlichen Angriffsvektor werden. Den Schlüssel kann man zB mit
openssl rand -base64 32
in einer Shell erzeugen und hier eintragen –> /etc/nutwatch/nutwatch.env danach das obligatorische
systemctl daemon-reload
systemctl restart nutwatch
Ich habe im weiteren Verlauf aber eine, zumindest aus meiner Sicht, bessere/sicherere Lösung für das Problem gefunden.
Das Paket nut muss auf PVE installiert werden, falls noch nicht bereits geschehen.
apt install nut
Zunächst habe ich sicher gestellt dass die systemd Dienste nut-monitor.service und nut-server.service bei Hängern oder Abstürzen neu gestartet werden. Das geht einfach mit einem override und somit mit systemd Bordmitteln:
systemctl edit nut-monitor.service
hier muss man an der richtigen Stelle folgendes eintragen
### Editing /etc/systemd/system/nut-monitor.service.d/override.conf
### Anything between here and the comment below will become the contents of the drop-in file
[Unit]
StartLimitIntervalSec=0
[Service]
Restart=on-failure
RestartSec=5s
### Edits below this comment will be discarded
genau das Gleiche auch noch bei
systemctl edit nut-server.service
und
### Editing /etc/systemd/system/nut-server.service.d/override.conf
### Anything between here and the comment below will become the contents of the drop-in file
[Unit]
StartLimitIntervalSec=0
[Service]
Restart=on-failure
RestartSec=5s
### Edits below this comment will be discarded
und systemd bekanntgeben sowie die beiden Dienste mit den overrides neu starten
systemctl daemon-reload
systemctl restart nut-monitor nut-server
man sollte den aktiven override jetzt als Drop-In im Status beider Dienste sehen
root@pve03:~# systemctl status nut-server
● nut-server.service - Network UPS Tools - power devices information server
Loaded: loaded (/usr/lib/systemd/system/nut-server.service; enabled; preset: enabled)
Drop-In: /etc/systemd/system/nut-server.service.d
└─override.conf
Active: active (running) since Wed 2026-07-08 10:19:44 CEST; 2h 27min ago
Jetzt noch ein Script anlegen, das den NUT Driver überwacht und bei Bedarf neu startet. Bei dem Script wird eine Nachricht, je nach Ereignis, per sendmail an root geschickt. Das PVE Notification System fängt solche Nachrichten ab und sendet sie an das eingestellte Ziel (meine Email Adresse in diesem Fall) weiter. Das versenden solcher Emails kann man zB mit
echo "Testinhalt" | sendmail root
testen. Nun das Script anlegen mit dem der NUT Driver überwacht werden soll, dies braucht leider ein bisschen mehr Logik.
nano /root/watchdog.sh
mit folgendem Inhalt (hier gehts zur aktuellen Version bei Github
#!/bin/bash
#
# /root/nut-watchdog.sh
set -euo pipefail
UPSNAME="usv-giesing"
HOST="localhost"
DRIVER_SERVICE="nut-driver@${UPSNAME}.service"
TIMEOUT_SEC=5
LOCKFILE="/var/run/nut-watchdog.lock"
STATEFILE="/var/run/nut-watchdog.laststart"
STATUSFILE="/var/run/nut-watchdog.status"
COOLDOWN_SEC=300
exec 9>"$LOCKFILE"
flock -n 9 || exit 0
log() {
logger -t nut-watchdog "$1"
}
notify_pve() {
local subject="$1"
local body="$2"
{
echo "To: root"
echo "Subject: ${subject}"
echo
echo "${body}"
} | /usr/sbin/sendmail -t
}
last_status="ok"
[ -f "$STATUSFILE" ] && last_status=$(cat "$STATUSFILE") || true
mark_ok() {
if [ "$last_status" = "fail" ]; then
log "INFO: RECOVERY - ${UPSNAME}@${HOST} ist wieder erreichbar"
notify_pve "NUT Watchdog: ${UPSNAME} auf $(hostname) wieder erreichbar"
"upsc kann ${UPSNAME}@${HOST} wieder erfolgreich abfragen. Problem ist behoben."
fi
echo "ok" > "$STATUSFILE"
}
mark_fail() {
echo "fail" > "$STATUSFILE"
}
# Erster Check
if timeout "$TIMEOUT_SEC" upsc "${UPSNAME}@${HOST}" ups.status >/dev/null 2>&1; then
mark_ok
exit 0
fi
log "WARN: upsc konnte ${UPSNAME}@${HOST} nicht abfragen - zweiter Versuch in 5s"
sleep 5
# Zweiter Check
if timeout "$TIMEOUT_SEC" upsc "${UPSNAME}@${HOST}" ups.status >/dev/null 2>&1; then
log "INFO: zweiter Versuch erfolgreich, kein Neustart nötig"
mark_ok
exit 0
fi
mark_fail
now=$(date +%s)
last=0
[ -f "$STATEFILE" ] && last=$(cat "$STATEFILE") || true
if [ $((now - last)) -lt "$COOLDOWN_SEC" ]; then
log "ERROR: ${UPSNAME} weiterhin nicht erreichbar, Cooldown aktiv - kein erneuter Neustart"
notify_pve "NUT Watchdog: ${UPSNAME} auf $(hostname) weiterhin down"
"Der Treiber ${DRIVER_SERVICE} antwortet seit dem letzten Neustart-Versuch weiterhin nicht. Cooldown aktiv, manuelle Prüfung nötig."
exit 1
fi
log "ERROR: ${UPSNAME} antwortet nicht, starte ${DRIVER_SERVICE} neu"
systemctl restart "$DRIVER_SERVICE"
echo "$now" > "$STATEFILE"
notify_pve "NUT Watchdog: ${UPSNAME} auf $(hostname) neu gestartet"
"upsc konnte ${UPSNAME}@${HOST} nicht abfragen, ${DRIVER_SERVICE} wurde automatisch neu gestartet."
Man muss bei dem Script lediglich der Wert für UPSNAME anpassen. Das Script wird bei mir als cronjob alle 2 Minuten ausgeführt. Man trägt dazu einfach das Script in der crontab ein. Der NUT Driver wird nun, zumindest bei mir, zuverlässig neu gestartet. Aktuell verliert PVE ca. 2-3x/Tag die Verbindung. Ich bekomme aber nun endlich mit, wann das immer passiert und finde evtl. so raus, womit das zusammenhängt.