feat(updater): --check/--version, --force-update mit Rollback, --update-only, systemd-Timer + Windows-Task; VERSION+SHA-Marker; envsubst-Fallback

This commit is contained in:
mm committed 2026-09-13 23:44:02 +02:00
1 parent 0e9dce9e47
commit 8d05d3bc48
3 files changed
+464 -6

No files matched your search

+298 -5
View File
@@ -22,6 +22,14 @@
# --pve-url <u> PVE-API-URL (Default: https://127.0.0.1:8006/api2/json)
# --apache-log <p> Apache-Access-Log (Default: /var/log/apache2/access.log)
# --uninstall Telegraf + Konfiguration entfernen
# --check Nur Versionsvergleich, nichts aendern (Exit 0 = aktuell)
# --version Installierte und verfuegbare Version ausgeben
# --force-update Confs/Scripts IMMER neu schreiben + Dienst neu starten
# --update-only Nur Confs/Scripts aktualisieren (kein Paket, kein Restart
# ohne Aenderung) — wird vom Auto-Updater-Timer genutzt
# --install-update-timer [daily|hourly|weekly|<N>min]
# systemd-Timer fuer den Auto-Updater einrichten
# --remove-update-timer Timer wieder entfernen
# ============================================================================
set -eu
@@ -38,8 +46,15 @@ PVE_NODE="${PVE_NODE:-}"
PVE_URL="${PVE_URL:-}"
APACHE_LOG="/var/log/apache2/access.log"
TELEGRAF_VERSION="${TELEGRAF_VERSION:-1.40.0}"
REPO_RAW="https://gitea.m-m.bio/mm/netbird-telegraf-installer/raw/branch/main"
# Ueberschreibbar (Tests/Mirror): REPO_RAW=... sh install.sh
REPO_RAW="${REPO_RAW:-https://gitea.m-m.bio/mm/netbird-telegraf-installer/raw/branch/main}"
UNINSTALL=0
CHECK=0
SHOW_VERSION=0
FORCE_UPDATE=0
UPDATE_ONLY=0
TIMER_INTERVAL=""
REMOVE_TIMER=0
while [ $# -gt 0 ]; do
case "$1" in
@@ -52,6 +67,17 @@ while [ $# -gt 0 ]; do
--pve-url) PVE_URL="$2"; shift 2 ;;
--apache-log) APACHE_LOG="$2"; shift 2 ;;
--uninstall) UNINSTALL=1; shift ;;
--check) CHECK=1; shift ;;
--version) SHOW_VERSION=1; shift ;;
--force-update) FORCE_UPDATE=1; shift ;;
--update-only) UPDATE_ONLY=1; shift ;;
--install-update-timer)
TIMER_INTERVAL="${2:-daily}"
case "$TIMER_INTERVAL" in
daily|hourly|weekly|[0-9]*min|[0-9]*) shift 2 ;;
*) TIMER_INTERVAL="daily"; shift ;;
esac ;;
--remove-update-timer) REMOVE_TIMER=1; shift ;;
-h|--help) sed -n '2,24p' "$0"; exit 0 ;;
*) echo "Unbekannte Option: $1" >&2; exit 2 ;;
esac
@@ -61,6 +87,19 @@ log() { printf '\033[1;34m[netbird-telegraf]\033[0m %s\n' "$*"; }
die() { printf '\033[1;31m[netbird-telegraf] FEHLER:\033[0m %s\n' "$*" >&2; exit 1; }
[ "$(id -u)" -eq 0 ] || die "Bitte als root ausführen (sudo)."
# Reine Abfragen brauchen keinen Token und kein root (Timer-Verwaltung schon).
if [ "$SHOW_VERSION" -eq 1 ] || [ "$CHECK" -eq 1 ]; then
LOCAL_V="$(cat /etc/telegraf/CONFIG_VERSION 2>/dev/null || echo 'nicht installiert')"
REMOTE_V="$(curl -fsS -m 15 "$REPO_RAW/VERSION" 2>/dev/null | tr -d ' \r\n')"
[ -n "$REMOTE_V" ] || REMOTE_V="nicht erreichbar"
printf 'installiert: %s\nverfuegbar: %s\n' "$LOCAL_V" "$REMOTE_V"
[ "$CHECK" -eq 1 ] || exit 0
if [ "$LOCAL_V" = "$REMOTE_V" ] && [ -n "$LOCAL_V" ] && [ "$LOCAL_V" != "nicht installiert" ]; then
echo "Status: aktuell"; exit 0
fi
echo "Status: Update verfuegbar"; exit 10
fi
[ -n "$TELEGRAF_TOKEN" ] || die "Kein Token: --token <Bearer-Token> angeben (siehe README)."
if [ -n "${COLLECTOR:-}" ]; then
@@ -129,6 +168,20 @@ if command -v curl >/dev/null; then
fi
fi
# --------------------------------------------------------------------------
# Update-Only: nur Konfiguration und Hilfsscripts aktualisieren.
# Kein Paket installieren, /etc/default/telegraf unangetastet lassen (Token!),
# Dienst nur neu starten, wenn sich wirklich etwas geaendert hat.
# --------------------------------------------------------------------------
SNAPSHOT_BEFORE=""
if [ "$UPDATE_ONLY" -eq 1 ]; then
SNAPSHOT_BEFORE="$(mktemp)"
cat /etc/telegraf/telegraf.d/*.conf /etc/telegraf/telegraf.conf 2>/dev/null > "$SNAPSHOT_BEFORE" || true
for s in journal-tail syslog-tail node-info proxmox-ve gpu-rocm; do
[ -f "/etc/telegraf/$s.sh" ] && cat "/etc/telegraf/$s.sh" >> "$SNAPSHOT_BEFORE" 2>/dev/null
done
fi
# --------------------------------------------------------------------------
# Installation
# --------------------------------------------------------------------------
@@ -196,6 +249,7 @@ EOF
if command -v telegraf >/dev/null 2>&1 || [ -x /usr/local/bin/telegraf ]; then
log "Telegraf bereits installiert ($(telegraf --version 2>/dev/null || /usr/local/bin/telegraf --version))."
[ "$UPDATE_ONLY" -eq 1 ] && log "Update-Only: Paketinstallation uebersprungen."
else
case "$OS_ID" in
debian|ubuntu|raspbian|linuxmint|pop) install_apt ;;
@@ -222,6 +276,9 @@ mkdir -p /etc/telegraf/telegraf.d /etc/default
umask 077
cat > /etc/default/telegraf <<EOF
NODE_NAME=$NODE_NAME
# ROLE/COLLECTOR/PVE_* braucht der Auto-Updater, um das Profil zu erhalten
# (sonst verliert ein PVE-Knoten beim Update seine Rolle).
ROLE=$ROLE
COLLECTOR=${COLLECTOR:-}
PROM_URL=$PROM_URL
LOKI_URL=$LOKI_URL
@@ -235,11 +292,30 @@ umask 022
fetch() { curl -fsSL "$REPO_RAW/$1" -o "$2" || die "Download $1 fehlgeschlagen."; }
# Ersatz fuer envsubst, falls gettext fehlt (Minimal-Container, schlanke
# Alpine-/Rocky-Installationen). Ersetzt nur die uebergebenen Variablennamen —
# gleiche Semantik wie envsubst mit expliziter Liste.
subst_vars() { # $1 = Quelldatei, $2 = Zieldatei, rest = Variablennamen
_src="$1"; _dst="$2"; shift 2
cp "$_src" "$_dst"
for _v in "$@"; do
eval "_val=\${$_v-}"
# Wert mit | als Trenner, Sonderzeichen via awk ersetzen (kein sed-Gebastel)
awk -v name="$_v" -v val="$_val" '{
gsub("\$\{" name "\}", val); print
}' "$_dst" > "$_dst.tmp" && mv "$_dst.tmp" "$_dst"
done
}
# Holt eine Conf und ersetzt ${...}-Platzhalter aus /etc/default/telegraf.
fetch_conf() {
fetch "$1" "$2.tmp"
set -a; [ -r /etc/default/telegraf ] && . /etc/default/telegraf; set +a
envsubst '${NODE_NAME} ${PROM_URL} ${LOKI_URL} ${TELEGRAF_TOKEN} ${PVE_TOKEN} ${PVE_NODE} ${PVE_URL} ${APACHE_LOG}' < "$2.tmp" > "$2"
if command -v envsubst >/dev/null; then
envsubst '${NODE_NAME} ${PROM_URL} ${LOKI_URL} ${TELEGRAF_TOKEN} ${PVE_TOKEN} ${PVE_NODE} ${PVE_URL} ${APACHE_LOG}' < "$2.tmp" > "$2"
else
subst_vars "$2.tmp" "$2" NODE_NAME PROM_URL LOKI_URL TELEGRAF_TOKEN PVE_TOKEN PVE_NODE PVE_URL APACHE_LOG
fi
if grep -q '\${' "$2"; then
log "WARNUNG: $2 enthaelt noch unaufgeloeste Platzhalter:"
grep -o '\${[A-Z_]*}' "$2" | sort -u >&2
@@ -334,10 +410,47 @@ EOF
esac
chown -R telegraf:telegraf /etc/telegraf 2>/dev/null || true
# --------------------------------------------------------------------------
# Force-Update: Confs und Hilfsscripts erzwungen neu schreiben.
# Laeuft VOR dem Konfig-Test, damit ein Rollback unten greifen kann.
# --------------------------------------------------------------------------
write_conf_backups() { # Sicherung fuer den Rollback
BK="/var/backups/telegraf-$(date +%Y%m%d-%H%M%S)"
mkdir -p "$BK"
cp -a /etc/telegraf/telegraf.d "$BK/" 2>/dev/null || true
cp -a /etc/telegraf/telegraf.conf "$BK/" 2>/dev/null || true
printf '%s' "$BK" > /var/lib/telegraf-last-backup
}
rollback_conf() { # letzte Sicherung zurueckspielen
BK="$(cat /var/lib/telegraf-last-backup 2>/dev/null || true)"
[ -n "$BK" ] && [ -d "$BK/telegraf.d" ] || return 1
rm -rf /etc/telegraf/telegraf.d
cp -a "$BK/telegraf.d" /etc/telegraf/telegraf.d
[ -f "$BK/telegraf.conf" ] && cp -a "$BK/telegraf.conf" /etc/telegraf/telegraf.conf
log "Rollback aus $BK"
}
if [ "$FORCE_UPDATE" -eq 1 ]; then
write_conf_backups
log "Force-Update: Confs und Scripts werden neu geschrieben."
fi
# Konfig testen
TG="$(command -v telegraf || echo /usr/local/bin/telegraf)"
set -a; . /etc/default/telegraf; set +a
"$TG" --config /etc/telegraf/telegraf.conf --config-directory /etc/telegraf/telegraf.d --test --input-filter cpu:mem >/dev/null 2>&1 || die "Konfiguration ungültig — telegraf --test prüfen."
if ! "$TG" --config /etc/telegraf/telegraf.conf --config-directory /etc/telegraf/telegraf.d --test --input-filter cpu:mem >/dev/null 2>&1; then
# Bei Force-/Auto-Update zuerst zurueckrollen, dann erst aufgeben.
if [ "$FORCE_UPDATE" -eq 1 ] || [ "$UPDATE_ONLY" -eq 1 ]; then
log "Konfiguration ungültig — Rollback auf die letzte Sicherung."
rollback_conf || true
"$TG" --config /etc/telegraf/telegraf.conf --config-directory /etc/telegraf/telegraf.d --test --input-filter cpu:mem >/dev/null 2>&1 \
|| die "Konfiguration auch nach Rollback ungültig — telegraf --test prüfen."
log "Rollback erfolgreich, alte Konfiguration aktiv."
else
die "Konfiguration ungültig — telegraf --test prüfen."
fi
fi
# --------------------------------------------------------------------------
# Dienst
@@ -355,10 +468,37 @@ EOF
log "Proxmox: systemd-Drop-in gesetzt — Dienst laeuft als root (pvesh braucht root)."
fi
CHANGED=1
if [ "$UPDATE_ONLY" -eq 1 ] && [ -n "$SNAPSHOT_BEFORE" ]; then
SNAPSHOT_AFTER="$(mktemp)"
cat /etc/telegraf/telegraf.d/*.conf /etc/telegraf/telegraf.conf 2>/dev/null > "$SNAPSHOT_AFTER" || true
for s in journal-tail syslog-tail node-info proxmox-ve gpu-rocm; do
[ -f "/etc/telegraf/$s.sh" ] && cat "/etc/telegraf/$s.sh" >> "$SNAPSHOT_AFTER" 2>/dev/null
done
if cmp -s "$SNAPSHOT_BEFORE" "$SNAPSHOT_AFTER"; then CHANGED=0; fi
rm -f "$SNAPSHOT_BEFORE" "$SNAPSHOT_AFTER"
if [ "$CHANGED" -eq 0 ]; then
log "Update-Only: keine Aenderung an Confs/Scripts — kein Neustart noetig."
# Versionsmarker TROTZDEM auf den Repo-Stand ziehen: sonst meldet der
# naechste Timer-Lauf erneut ein Update und laeuft endlos im Kreis.
_RV="$(curl -fsS -m 15 "$REPO_RAW/VERSION" 2>/dev/null | tr -d ' \r\n' || true)"
[ -n "$_RV" ] && printf '%s\n' "$_RV" > /etc/telegraf/CONFIG_VERSION
_RS="$(curl -fsS -m 20 "$REPO_RAW/install.sh" 2>/dev/null | { command -v sha256sum >/dev/null && sha256sum || shasum -a 256; } | cut -d' ' -f1 || true)"
[ -n "$_RS" ] && printf '%s\n' "$_RS" > /etc/telegraf/INSTALLER_SHA
printf '%s\n' "$REPO_RAW" > /etc/telegraf/REPO_RAW
exit 0
fi
log "Update-Only: Aenderungen erkannt — Dienst wird neu gestartet."
fi
if command -v systemctl >/dev/null && [ -d /run/systemd/system ]; then
systemctl daemon-reload
systemctl enable --now telegraf >/dev/null
systemctl restart telegraf
if [ "$UPDATE_ONLY" -eq 1 ]; then
systemctl restart telegraf
else
systemctl enable --now telegraf >/dev/null
systemctl restart telegraf
fi
sleep 3
if ! systemctl is-active --quiet telegraf; then
journalctl -u telegraf -n 20 --no-pager
@@ -385,6 +525,159 @@ fi
PROM_BASE="$(printf '%s' "$PROM_URL" | sed -E 's#/api/v1/write/?$##')"
[ "$GPU" != "none" ] && log "GPU=$GPU erfasst. Hinweis: im Docker-Betrieb muss der GPU-Treiber im Container verfuegbar sein (nvidia-container-toolkit bzw. /dev/dri-Mount); im systemd-Betrieb ist das automatisch der Fall."
# --------------------------------------------------------------------------
# Versionsmarker fuer den Auto-Updater
# --------------------------------------------------------------------------
REMOTE_V="$(curl -fsS -m 15 "$REPO_RAW/VERSION" 2>/dev/null | tr -d ' \r\n' || true)"
printf '%s\n' "${REMOTE_V:-unbekannt}" > /etc/telegraf/CONFIG_VERSION
# Aktive Repo-Quelle festhalten, damit der Auto-Updater denselben Weg nutzt.
printf '%s\n' "$REPO_RAW" > /etc/telegraf/REPO_RAW
# Hash der Installer-Logik: erkennt auch Aenderungen ohne Versionssprung
# (z.B. eine Korrektur an journal-tail.sh).
if curl -fsS -m 20 "$REPO_RAW/install.sh" -o /tmp/.tg-installer.sha 2>/dev/null; then
if command -v sha256sum >/dev/null; then sha256sum /tmp/.tg-installer.sha | cut -d' ' -f1 > /etc/telegraf/INSTALLER_SHA
elif command -v shasum >/dev/null; then shasum -a 256 /tmp/.tg-installer.sha | cut -d' ' -f1 > /etc/telegraf/INSTALLER_SHA
fi
rm -f /tmp/.tg-installer.sha
fi
chmod 0644 /etc/telegraf/CONFIG_VERSION /etc/telegraf/INSTALLER_SHA 2>/dev/null || true
# --------------------------------------------------------------------------
# Auto-Updater-Timer
# --------------------------------------------------------------------------
install_update_timer() {
IV="${1:-daily}"
case "$IV" in
daily) ONCAL="*-*-* 04:30:00" ;;
hourly) ONCAL="*-*-* *:30:00" ;;
weekly) ONCAL="Mon *-*-* 04:30:00" ;;
*min) ONCAL="" ;; # OnUnitActiveSec statt OnCalendar
*) ONCAL="*-*-* 04:30:00" ;;
esac
# Der Updater holt sich das Script frisch und ruft sich selbst mit
# --update-only auf. Token kommt aus /etc/default/telegraf (nicht im Repo).
cat > /usr/local/bin/telegraf-installer-update <<'UPD'
#!/bin/sh
# Auto-Updater: nur bei echter Aenderung etwas tun.
set -u
# Repo-Quelle: aus der Umgebung, sonst aus der beim Install hinterlegten
# Datei, sonst Default. So funktioniert der Updater auch mit Mirror/Testserver.
REPO_RAW="${REPO_RAW:-$(cat /etc/telegraf/REPO_RAW 2>/dev/null || echo https://gitea.m-m.bio/mm/netbird-telegraf-installer/raw/branch/main)}"
LOG="/var/log/telegraf-installer-update.log"
say() { printf '%s %s\n' "$(date -Is)" "$*" >> "$LOG"; }
LOCAL_V="$(cat /etc/telegraf/CONFIG_VERSION 2>/dev/null || echo '')"
REMOTE_V="$(curl -fsS -m 20 "$REPO_RAW/VERSION" 2>/dev/null | tr -d ' \r\n' || true)"
[ -n "$REMOTE_V" ] || { say "Repo nicht erreichbar (NetBird down?) — kein Update."; exit 0; }
NEED=0
[ "$LOCAL_V" != "$REMOTE_V" ] && NEED=1
# Hash-Vergleich: erkennt Script-Fixes ohne Versionssprung
if [ "$NEED" -eq 0 ] && command -v sha256sum >/dev/null; then
TMP="$(mktemp)"; curl -fsS -m 25 "$REPO_RAW/install.sh" -o "$TMP" 2>/dev/null || true
if [ -s "$TMP" ]; then
R_SHA="$(sha256sum "$TMP" | cut -d' ' -f1)"
L_SHA="$(cat /etc/telegraf/INSTALLER_SHA 2>/dev/null || echo '')"
[ "$R_SHA" != "$L_SHA" ] && NEED=1
fi
rm -f "$TMP"
fi
if [ "$NEED" -eq 0 ]; then
say "aktuell ($LOCAL_V) — nichts zu tun."
exit 0
fi
say "Update $LOCAL_V -> $REMOTE_V"
TMPI="$(mktemp)"
if ! curl -fsS -m 60 "$REPO_RAW/install.sh" -o "$TMPI" 2>/dev/null; then
say "Download fehlgeschlagen."; rm -f "$TMPI"; exit 1
fi
# --update-only: nur Confs/Scripts, kein Paket, kein Tokenwechsel.
# WICHTIG: REPO_RAW und die Node-Identitaet muessen mitgegeben werden, sonst
# faellt NODE_NAME auf den Hostnamen der AUFRUFENDEN Maschine zurueck und der
# Unterlauf holt die Version von der falschen Quelle.
UPD_NAME="$(sed -n 's/^NODE_NAME=//p' /etc/default/telegraf 2>/dev/null | head -1)"
UPD_ROLE="$(sed -n 's/^ROLE=//p' /etc/default/telegraf 2>/dev/null | head -1)"
UPD_TOKEN="$(sed -n 's/^TELEGRAF_TOKEN=//p' /etc/default/telegraf 2>/dev/null | head -1)"
UPD_COLL="$(sed -n 's/^COLLECTOR=//p' /etc/default/telegraf 2>/dev/null | head -1)"
[ -n "$UPD_NAME" ] || UPD_NAME="$(hostname -s)"
set -- --update-only --name "$UPD_NAME" --token "$UPD_TOKEN"
[ -n "$UPD_ROLE" ] && set -- "$@" --role "$UPD_ROLE"
[ -n "$UPD_COLL" ] && set -- "$@" --collector "$UPD_COLL"
if REPO_RAW="$REPO_RAW" sh "$TMPI" "$@" >> "$LOG" 2>&1; then
say "Update erfolgreich."
else
say "Update FEHLGESCHLAGEN — siehe oben. Alte Konfiguration bleibt aktiv."
fi
rm -f "$TMPI"
UPD
chmod 0755 /usr/local/bin/telegraf-installer-update
if [ -d /etc/systemd/system ]; then
cat > /etc/systemd/system/telegraf-installer-update.service <<'EOF'
[Unit]
Description=Telegraf-Installer Auto-Update (nur bei Aenderung)
After=network-online.target
Wants=network-online.target
[Service]
Type=oneshot
ExecStart=/usr/local/bin/telegraf-installer-update
EOF
if [ -n "$ONCAL" ]; then
cat > /etc/systemd/system/telegraf-installer-update.timer <<EOF
[Unit]
Description=Taeglicher Telegraf-Installer Auto-Update
[Timer]
OnCalendar=$ONCAL
Persistent=true
RandomizedDelaySec=15m
[Install]
WantedBy=timers.target
EOF
else
cat > /etc/systemd/system/telegraf-installer-update.timer <<EOF
[Unit]
Description=Telegraf-Installer Auto-Update ($IV)
[Timer]
OnBootSec=$IV
OnUnitActiveSec=$IV
Persistent=true
[Install]
WantedBy=timers.target
EOF
fi
systemctl daemon-reload
systemctl enable --now telegraf-installer-update.timer >/dev/null 2>&1 \
&& log "Auto-Updater aktiv ($IV) — Log: /var/log/telegraf-installer-update.log" \
|| log "WARNUNG: Timer konnte nicht aktiviert werden (systemd nicht aktiv?)."
else
log "HINWEIS: kein systemd — Auto-Updater nur manuell (telegraf-installer-update)."
fi
}
remove_update_timer() {
command -v systemctl >/dev/null 2>&1 || { log "Auto-Updater: systemctl fehlt — Dateien werden entfernt."; rm -f /etc/systemd/system/telegraf-installer-update.timer /etc/systemd/system/telegraf-installer-update.service /usr/local/bin/telegraf-installer-update; return 0; }
systemctl disable --now telegraf-installer-update.timer >/dev/null 2>&1 || true
rm -f /etc/systemd/system/telegraf-installer-update.timer \
/etc/systemd/system/telegraf-installer-update.service \
/usr/local/bin/telegraf-installer-update
systemctl daemon-reload 2>/dev/null || true
log "Auto-Updater entfernt."
}
if [ "$REMOVE_TIMER" -eq 1 ]; then
if command -v systemctl >/dev/null 2>&1; then remove_update_timer
else log "Auto-Updater: kein systemd — nichts zu entfernen."; fi
fi
if [ -n "$TIMER_INTERVAL" ]; then install_update_timer "$TIMER_INTERVAL"; fi
log "OK — Node '$NODE_NAME' liefert an $PROM_URL (Metriken) und $LOKI_URL (Logs)."
log "Prüfen: curl -s -H 'Authorization: Bearer <TOKEN>' '$PROM_BASE/api/v1/query?query=system_uptime{node=\"$NODE_NAME\"}'"
log "Grafana: http://100.83.134.46:3000 (nur im NetBird)"