x14 blieb nach der letzten Erfolgsmeldung stehen (Abbruch per ^C, kein Fehler). Ursache: grant_apache_log_access() ruft apt-get install acl auf — OHNE apt-get update davor und OHNE Timeout. Bei veralteten Paketlisten kann apt in eine Rueckfrage laufen und unbegrenzt warten. Direkt danach haette der naechste fetch gehangen: fetch() hatte ueberhaupt kein curl-Timeout. Fix: - apt-get update vor dem acl-Install, timeout 180 auf allen Paketmanager-Aufrufen - fetch() mit -m 30 + 3 Versuchen statt unbegrenztem Warten - alle weiteren curl-Aufrufe (keyring, Binary, Re-Exec) mit -m/--connect-timeout - Fortschrittsmeldung vor der ACL-Phase: ein Haenger sah wie ein Absturz aus
1156 lines
52 KiB
Bash
Executable File
1156 lines
52 KiB
Bash
Executable File
#!/usr/bin/env sh
|
|
# ============================================================================
|
|
# SELBSTSCHUTZ BEI "curl | sh"
|
|
#
|
|
# Problem (real passiert, x14): Bei `curl … | sh` liest die Shell das Skript aus
|
|
# STDIN. Jeder Unterbefehl, der stdin genauso liest, frisst den Rest des
|
|
# Skripts — die Shell setzt dann mitten im Quelltext fort und bricht ab.
|
|
# Ausloeser ist apt/dpkg: auf Ubuntu laeuft dabei `needrestart`, und das
|
|
# meldet sich mit "Scanning processes... / Scanning linux images...".
|
|
# Symptom in der Praxis: Der Installer gibt seinen EIGENEN Quelltext aus
|
|
# ("; then", "fi", Kommentarzeilen) und bleibt mitten in der Installation stehen.
|
|
# Auf Nodes mit bereits installiertem Telegraf tritt das NICHT auf (kein apt).
|
|
#
|
|
# Loesung: Laeuft das Skript ueber eine Pipe, kopiert es sich EINMAL auf die
|
|
# Platte und startet sich von dort neu. Ab da ist stdin frei und apt kann
|
|
# nichts mehr verschlucken. Idempotent: der Neustart setzt die Marker-Variable.
|
|
# ============================================================================
|
|
# Nur bei einer ECHTEN PIPE (curl … | sh) neu starten. Bei `sh install.sh`
|
|
# oder `sh install.sh < eingabe` ist stdin eine Datei — dort kann kein
|
|
# Unterbefehl das Skript wegfressen, und der Re-Exec waere nur ein
|
|
# unnoetiger Download.
|
|
if [ -z "${NETBIRD_TG_REEXEC:-}" ] && [ ! -t 0 ] && [ -p /dev/stdin ]; then
|
|
# Das Skript wird NICHT per `cat` von stdin kopiert: die Shell liest stdin
|
|
# blockweise und hat den Anfang bereits gepuffert — `cat` bekaeme nur den
|
|
# Rest und die Kopie waere unvollstaendig. Stattdessen frisch von der Quelle
|
|
# laden (dieselbe URL, die der Aufrufer benutzt hat).
|
|
_src="${REPO_RAW:-https://gitea.m-m.bio/mm/netbird-telegraf-installer/raw/branch/main}"
|
|
_self="$(mktemp /tmp/netbird-telegraf-install.XXXXXX 2>/dev/null || echo /tmp/netbird-tg.$$)"
|
|
|
|
# WICHTIG: auf einem FRISCHEN System gibt es oft kein curl — genau dort, wo
|
|
# der Schutz am noetigsten ist (dort laeuft apt und damit needrestart).
|
|
# Deshalb BEIDE Wege versuchen und, wenn keiner geht, das Skript weiter
|
|
# ausfuehren wie bisher (dann bleibt das Risiko, aber es laeuft).
|
|
_dl=0
|
|
if command -v curl >/dev/null 2>&1; then
|
|
curl -fsSL -m 30 --connect-timeout 10 "$_src/install.sh" -o "$_self" 2>/dev/null && [ -s "$_self" ] && _dl=1
|
|
fi
|
|
if [ "$_dl" -eq 0 ] && command -v wget >/dev/null 2>&1; then
|
|
timeout 30 wget -q -O "$_self" "$_src/install.sh" 2>/dev/null && [ -s "$_self" ] && _dl=1
|
|
fi
|
|
if [ "$_dl" -eq 0 ] && command -v busybox >/dev/null 2>&1; then
|
|
busybox wget -q -O "$_self" "$_src/install.sh" 2>/dev/null && [ -s "$_self" ] && _dl=1
|
|
fi
|
|
# Letzter Weg: liegt das Skript schon lokal (z. B. per scp), von dort kopieren.
|
|
if [ "$_dl" -eq 0 ] && [ -n "${NETBIRD_TG_SOURCE:-}" ] && [ -s "${NETBIRD_TG_SOURCE:-}" ]; then
|
|
cp "${NETBIRD_TG_SOURCE}" "$_self" 2>/dev/null && _dl=1
|
|
fi
|
|
|
|
if [ "$_dl" -eq 1 ]; then
|
|
chmod 0700 "$_self"
|
|
printf '[netbird-telegraf] Selbstschutz: Skript laeuft jetzt von %s (stdin frei).\n' "$_self"
|
|
# stdin ausdruecklich auf /dev/null: der Prozess erbt sonst die Pipe, und
|
|
# apt/needrestart koennte weiter daraus lesen.
|
|
NETBIRD_TG_REEXEC=1 REPO_RAW="$_src" sh "$_self" "$@" < /dev/null
|
|
_rc=$?
|
|
rm -f "$_self"
|
|
exit "$_rc"
|
|
fi
|
|
printf '[netbird-telegraf] HINWEIS: kein curl/wget fuer den Selbstschutz — weiter ohne.\n'
|
|
rm -f "$_self"
|
|
fi
|
|
# ============================================================================
|
|
# NetBird Observability — Telegraf Node Installer (Linux)
|
|
#
|
|
# Installiert Telegraf als systemd-Dienst und verbindet die Node fest mit dem
|
|
# zentralen Collector auf dem imac (Prometheus Remote Write + Loki) im NetBird.
|
|
#
|
|
# Unterstützt: Debian/Ubuntu/Proxmox VE (apt), RHEL/Rocky/Alma/Fedora (dnf/yum),
|
|
# Alpine (apk, OpenRC), sonstige Linux via statischem Binary.
|
|
# Architekturen: amd64 / x86_64, arm64 / aarch64, armv7.
|
|
# Windows: install.ps1 verwenden.
|
|
#
|
|
# Nutzung (als root):
|
|
# curl -fsSL https://gitea.m-m.bio/mm/netbird-telegraf-installer/raw/branch/main/install.sh | sh -s -- --name <node-name>
|
|
# Optionen:
|
|
# --name <n> Node-Name (Default: hostname -s)
|
|
# --token <t> Bearer-Token des Reverse-Proxys (Pflicht)
|
|
# --collector <ip> Direktweg im NetBird statt Reverse Proxy
|
|
# --role <r> Zusatz-Profil: proxmox | apache | docker | none (Default: auto)
|
|
# --pve-token <t> Proxmox API-Token 'user@pve!name=secret' (nur --role proxmox)
|
|
# --pve-node <n> Name des PVE-Knotens im PVE-Baum (Default: per pvesh erkannt)
|
|
# --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
|
|
|
|
# Ausgang ueber den NetBird-Reverse-Proxy: funktioniert auch fuer Hosts, die
|
|
# KEIN NetBird-Peer sind (Büro-LAN, Kundenlaptop, CGNAT). Token erforderlich.
|
|
PROM_URL_DEFAULT="https://imac-prometheus.x05.idx.wf/api/v1/write"
|
|
LOKI_URL_DEFAULT="https://imac-loki.x05.idx.wf"
|
|
COLLECTOR="${COLLECTOR:-}" # nur setzen fuer den Direktweg im NetBird
|
|
TELEGRAF_TOKEN="${TELEGRAF_TOKEN:-}"
|
|
NODE_NAME="${NODE_NAME:-$(hostname -s 2>/dev/null || hostname)}"
|
|
ROLE="auto"
|
|
# Wurden --name/--role auf der Kommandozeile gesetzt? Nur dann darf ein
|
|
# Update-Lauf die in /etc/default/telegraf hinterlegten Werte ueberschreiben.
|
|
NAME_GIVEN=0
|
|
ROLE_GIVEN=0
|
|
PVE_TOKEN="${PVE_TOKEN:-}"
|
|
PVE_NODE="${PVE_NODE:-}"
|
|
PVE_URL="${PVE_URL:-}"
|
|
# Apache-Logpfad: Distributionen unterscheiden sich — Debian/Ubuntu/KeyHelp
|
|
# nutzen /var/log/apache2/, RHEL/Rocky /var/log/httpd/. Der Installer sucht beim
|
|
# ersten Lauf; --apache-log ueberschreibt.
|
|
APACHE_LOG=""
|
|
TELEGRAF_VERSION="${TELEGRAF_VERSION:-1.40.0}"
|
|
# 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
|
|
DIAGNOSE=0
|
|
FORCE_UPDATE=0
|
|
UPDATE_ONLY=0
|
|
TIMER_INTERVAL=""
|
|
REMOVE_TIMER=0
|
|
|
|
while [ $# -gt 0 ]; do
|
|
case "$1" in
|
|
--name) NODE_NAME="$2"; NAME_GIVEN=1; shift 2 ;;
|
|
--collector) COLLECTOR="${2:-}"; shift 2 ;;
|
|
--token) TELEGRAF_TOKEN="$2"; shift 2 ;;
|
|
--role) ROLE="$2"; ROLE_GIVEN=1; shift 2 ;;
|
|
--pve-token) PVE_TOKEN="$2"; shift 2 ;;
|
|
--pve-node) PVE_NODE="$2"; shift 2 ;;
|
|
--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 ;;
|
|
--diagnose) DIAGNOSE=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
|
|
done
|
|
|
|
log() { printf '\033[1;34m[netbird-telegraf]\033[0m %s\n' "$*"; }
|
|
|
|
# --------------------------------------------------------------------------
|
|
# Bestehende Installation: Werte aus /etc/default/telegraf nachladen
|
|
#
|
|
# WARUM: Der Auto-Updater liest Token, NODE_NAME und ROLE aus dieser Datei und
|
|
# gibt sie dem Unterlauf mit. Ein MANUELLER `--update-only`-Lauf tat das nicht
|
|
# und brach an der Token-Pruefung ab ("Kein Token"), obwohl der Token auf der
|
|
# Maschine liegt. Die Datei ist die Quelle der Wahrheit fuer eine bereits
|
|
# eingerichtete Node — die Kommandozeile ueberschreibt sie nur, wenn sie
|
|
# ausdruecklich etwas anderes sagt.
|
|
#
|
|
# Zweiter, stiller Fehler derselben Ursache: ohne --name fiel NODE_NAME auf den
|
|
# Hostnamen zurueck. Auf einem KeyHelp-Host heisst der Host aber nicht wie die
|
|
# Node ('x22' vs 'x22.idx.wf-keyhelp') — ein Update-Lauf haette die Node unter
|
|
# falschem Label neu registriert. Ebenso haette ein PVE-Knoten ohne --role seine
|
|
# Rolle auf 'auto' verloren (kein pvesh-Drop-in mehr).
|
|
# --------------------------------------------------------------------------
|
|
_rd_default() {
|
|
sed -n "s/^$1=//p" /etc/default/telegraf 2>/dev/null | head -1 \
|
|
| sed "s/^['\"]//; s/['\"]$//"
|
|
}
|
|
if [ -r /etc/default/telegraf ]; then
|
|
if [ -z "$TELEGRAF_TOKEN" ]; then
|
|
TELEGRAF_TOKEN="$(_rd_default TELEGRAF_TOKEN)"
|
|
[ -n "$TELEGRAF_TOKEN" ] && log "Token aus /etc/default/telegraf uebernommen."
|
|
fi
|
|
[ -z "$COLLECTOR" ] && COLLECTOR="$(_rd_default COLLECTOR)"
|
|
if [ "$NAME_GIVEN" -eq 0 ]; then
|
|
_n="$(_rd_default NODE_NAME)"
|
|
if [ -n "$_n" ] && [ "$_n" != "$NODE_NAME" ]; then
|
|
log "Node-Name aus /etc/default/telegraf uebernommen: $_n"
|
|
NODE_NAME="$_n"
|
|
fi
|
|
fi
|
|
if [ "$ROLE_GIVEN" -eq 0 ]; then
|
|
_r="$(_rd_default ROLE)"
|
|
if [ -n "$_r" ] && [ "$_r" != "none" ]; then
|
|
log "Rolle aus /etc/default/telegraf uebernommen: $_r"
|
|
ROLE="$_r"
|
|
fi
|
|
fi
|
|
[ -z "$PVE_NODE" ] && PVE_NODE="$(_rd_default PVE_NODE)"
|
|
[ -z "$PVE_URL" ] && PVE_URL="$(_rd_default PVE_URL)"
|
|
# APACHE_LOG kommt als gequotete Liste — die Quotes entfernt _rd_default.
|
|
fi
|
|
|
|
# /etc/default/telegraf robust einlesen. Ein direktes "." bricht die ganze
|
|
# Installation ab, wenn die Datei einen unquoted Wert mit Leerzeichen oder
|
|
# Sonderzeichen enthaelt (alte APACHE_LOG-Zeile mit zwei Pfaden:
|
|
# "sh: /etc/default/telegraf: /pfad/zwei.log: Permission denied" — genau das
|
|
# passierte auf x22 und blockierte jedes weitere Update).
|
|
# Deshalb: nur syntaktisch heile Dateien auswerten, sonst sichern und warnen.
|
|
load_defaults() {
|
|
[ -r /etc/default/telegraf ] || return 0
|
|
if sh -n /etc/default/telegraf >/dev/null 2>&1; then
|
|
set -a; . /etc/default/telegraf; set +a
|
|
return 0
|
|
fi
|
|
printf '\033[1;33m[netbird-telegraf] WARNUNG:\033[0m /etc/default/telegraf ist nicht auswertbar — wird neu geschrieben.\n'
|
|
_bad="/etc/default/telegraf.unlesbar.$(date +%s)"
|
|
cp -a /etc/default/telegraf "$_bad" 2>/dev/null || true
|
|
printf '\033[1;33m[netbird-telegraf]\033[0m Sicherung: %s\n' "$_bad"
|
|
return 0
|
|
}
|
|
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)."
|
|
# --------------------------------------------------------------------------
|
|
# --diagnose: prueft in EINEM Aufruf, warum ein Input nichts liefert.
|
|
# Prueft genau die Stellen, die schon still versagt haben:
|
|
# Rechte des Dienst-Benutzers, leere Dateien, Offset-Zustand, Parser-Fehler.
|
|
# --------------------------------------------------------------------------
|
|
if [ "$DIAGNOSE" -eq 1 ]; then
|
|
printf '=== Telegraf-Installer Diagnose ===\n'
|
|
TG="$(command -v telegraf || echo /usr/local/bin/telegraf)"
|
|
printf '\n-- Dienst --\n'
|
|
if command -v systemctl >/dev/null 2>&1; then
|
|
printf 'Status: %s\n' "$(systemctl is-active telegraf 2>/dev/null || echo unbekannt)"
|
|
printf 'Benutzer: %s\n' "$(systemctl show telegraf -p User --value 2>/dev/null || echo unbekannt)"
|
|
printf 'Gruppen: %s\n' "$(systemctl show telegraf -p SupplementaryGroups --value 2>/dev/null || echo -)"
|
|
fi
|
|
DBU="$(systemctl show telegraf -p User --value 2>/dev/null || echo telegraf)"
|
|
[ -n "$DBU" ] || DBU=telegraf
|
|
|
|
printf '\n-- Logpfade aus der aktiven Conf --\n'
|
|
CF="/etc/telegraf/telegraf.d/apache.conf"
|
|
[ -f "$CF" ] || CF="/etc/telegraf/telegraf.conf"
|
|
# Beide files-Zeilen (journal + apache_access) lesen, aber entdoppeln —
|
|
# sonst erscheint jeder Pfad zweimal in der Ausgabe.
|
|
_files="$(sed -n 's/^[[:space:]]*files = \[\(.*\)\].*/\1/p' "$CF" | tr -d '"' | tr ',' '\n' | sed 's/^ *//; s/ *$//' | grep -v '^$' | sort -u | tr '\n' ' ')"
|
|
[ -n "$_files" ] || { printf ' (keine files-Liste gefunden)\n'; }
|
|
_n=0; _ok=0; _empty=0; _noread=0
|
|
for _f in $_files; do
|
|
_n=$((_n+1))
|
|
if [ ! -e "$_f" ]; then printf ' FEHLT %s\n' "$_f"; continue; fi
|
|
_size="$(stat -c %s "$_f" 2>/dev/null || echo 0)"
|
|
if [ "$_size" -eq 0 ]; then printf ' LEER (0 B) %s\n' "$_f"; _empty=$((_empty+1)); continue; fi
|
|
# Lesbarkeit aus Sicht des Dienst-Benutzers — das war die stille Fehlerquelle.
|
|
if [ "$(id -u)" -eq 0 ] && command -v su >/dev/null 2>&1 && id "$DBU" >/dev/null 2>&1; then
|
|
# Dateiname fuer die Shell quoten (Pfade koennen Sonderzeichen haben)
|
|
_q="$(printf '%s' "$_f" | sed "s/'/'\\\\''/g")"
|
|
if su -s /bin/sh "$DBU" -c "head -c 1 '$_q' >/dev/null 2>&1"; then
|
|
printf ' OK %s (%s Bytes)\n' "$_f" "$_size"; _ok=$((_ok+1))
|
|
else
|
|
printf ' NICHT LESBAR %s (Benutzer %s) ← URSACHE\n' "$_f" "$DBU"; _noread=$((_noread+1))
|
|
fi
|
|
else
|
|
printf ' vorhanden %s (%s Bytes)\n' "$_f" "$_size"
|
|
fi
|
|
done
|
|
printf ' -> %s Pfade, %s lesbar, %s leer, %s nicht lesbar\n' "$_n" "$_ok" "$_empty" "$_noread"
|
|
|
|
printf '\n-- Parser-Test (ohne Offset-Zwang) --\n'
|
|
_out="$("$TG" --config /etc/telegraf/telegraf.conf --config-directory /etc/telegraf/telegraf.d --test --test-wait 2 2>&1)"
|
|
printf '%s\n' "$_out" | grep -c 'E!' | sed 's/^/ Fehlerzeilen: /'
|
|
printf '%s\n' "$_out" | grep -E 'E!' | head -3 | sed 's/^/ /'
|
|
printf '%s\n' "$_out" | grep -cE '^[>] ' | sed 's/^/ erzeugte Messungen: /'
|
|
|
|
printf '\n-- Offset-Zustand (erste Messung je Datei erst nach neuem Zugriff) --\n'
|
|
ls -la /var/lib/telegraf/ 2>/dev/null | tail -5 || printf ' (kein State-Verzeichnis)\n'
|
|
printf '\nHinweis: initial_read_offset = "saved-or-end" bedeutet, dass beim ERSTEN\n'
|
|
printf 'Lauf nur NEUES gelesen wird. Bestehende Zeilen kommen erst mit neuen\n'
|
|
printf 'Zugriffen. Fuer einen sofortigen Test: eine Datei anfordern und warten.\n'
|
|
exit 0
|
|
fi
|
|
|
|
# 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
|
|
PROM_URL="http://$COLLECTOR:9090/api/v1/write"; LOKI_URL="http://$COLLECTOR:3100"
|
|
log "Direktweg im NetBird: Collector $COLLECTOR"
|
|
else
|
|
PROM_URL="$PROM_URL_DEFAULT"; LOKI_URL="$LOKI_URL_DEFAULT"
|
|
fi
|
|
|
|
# --------------------------------------------------------------------------
|
|
# Uninstall
|
|
# --------------------------------------------------------------------------
|
|
if [ "$UNINSTALL" -eq 1 ]; then
|
|
log "Entferne Telegraf …"
|
|
systemctl disable --now telegraf 2>/dev/null || rc-service telegraf stop 2>/dev/null || true
|
|
if command -v apt-get >/dev/null; then apt-get remove -y telegraf >/dev/null 2>&1 || true
|
|
elif command -v dnf >/dev/null; then dnf remove -y telegraf >/dev/null 2>&1 || true
|
|
elif command -v yum >/dev/null; then yum remove -y telegraf >/dev/null 2>&1 || true
|
|
elif command -v apk >/dev/null; then apk del telegraf >/dev/null 2>&1 || true
|
|
fi
|
|
rm -rf /etc/telegraf /usr/local/bin/telegraf /etc/systemd/system/telegraf.service
|
|
systemctl daemon-reload 2>/dev/null || true
|
|
log "Fertig."
|
|
exit 0
|
|
fi
|
|
|
|
# --------------------------------------------------------------------------
|
|
# Erkennung: OS, Arch, Rolle
|
|
# --------------------------------------------------------------------------
|
|
OS_ID="unknown"; [ -r /etc/os-release ] && . /etc/os-release && OS_ID="${ID:-unknown}"
|
|
ARCH_RAW="$(uname -m)"
|
|
case "$ARCH_RAW" in
|
|
x86_64|amd64) ARCH="amd64" ;;
|
|
aarch64|arm64) ARCH="arm64" ;;
|
|
armv7l|armhf) ARCH="armhf" ;;
|
|
*) die "Architektur $ARCH_RAW wird nicht unterstützt." ;;
|
|
esac
|
|
|
|
IS_PVE=0; command -v pveversion >/dev/null 2>&1 && IS_PVE=1
|
|
HAS_DOCKER=0; [ -S /var/run/docker.sock ] && HAS_DOCKER=1
|
|
GPU="none"
|
|
if command -v nvidia-smi >/dev/null 2>&1 && nvidia-smi -L >/dev/null 2>&1; then
|
|
GPU="nvidia"
|
|
elif command -v rocm-smi >/dev/null 2>&1; then
|
|
GPU="amd"
|
|
elif [ -e /dev/dri/renderD128 ]; then
|
|
GPU="intel"
|
|
fi
|
|
HAS_APACHE=0; { command -v apache2ctl >/dev/null 2>&1 || command -v httpd >/dev/null 2>&1; } && HAS_APACHE=1
|
|
if [ "$HAS_APACHE" -eq 1 ] && [ -z "$APACHE_LOG" ]; then
|
|
# ---------------------------------------------------------------------------
|
|
# Apache-Logpfade ermitteln — MUSTER, nicht expandierte Einzelpfade.
|
|
#
|
|
# Warum Muster: KeyHelp/Plesk legen pro Domain eigene Logs an, und es kommen
|
|
# laufend neue dazu. Eine Conf mit 43 festen Pfaden verliert jede neue Domain,
|
|
# bis der Installer erneut laeuft. Ein Glob deckt sie sofort mit ab.
|
|
#
|
|
# Verifizierte Strukturen (auf x22 real vorgefunden):
|
|
# KeyHelp : /home/users/<user>/logs/<domain>/access.log (zweistufig!)
|
|
# /var/log/apache2/<vhost>/access.log (z.B. keyhelp/)
|
|
# Plesk : /var/www/vhosts/<domain>/logs/access_log
|
|
# cPanel : /usr/local/apache/domlogs/<domain>
|
|
# klassisch: /var/log/apache2/access.log, /var/log/httpd/access_log
|
|
# ---------------------------------------------------------------------------
|
|
_pats=""
|
|
for _pat in \
|
|
"/var/log/apache2/*/access.log" \
|
|
"/home/users/*/logs/*/access.log" \
|
|
"/home/*/logs/*/access.log" \
|
|
"/var/www/vhosts/*/logs/access_log" \
|
|
"/usr/local/apache/domlogs/*" \
|
|
"/var/log/httpd/*access*.log" \
|
|
"/var/log/apache2/*/error.log" \
|
|
"/home/users/*/logs/*/error.log" \
|
|
"/home/*/logs/*/error.log" \
|
|
"/var/log/apache2/error.log" \
|
|
"/var/log/httpd/*error*.log"; do
|
|
# shellcheck disable=SC2086
|
|
if ls $_pat >/dev/null 2>&1; then
|
|
_pats="$_pats $_pat"
|
|
fi
|
|
done
|
|
# Klassische Einzeldateien nur, wenn sie NICHT leer sind: auf KeyHelp ist
|
|
# /var/log/apache2/access.log vorhanden, aber 0 Bytes — ein Input darauf
|
|
# liefert still nichts.
|
|
for _p in /var/log/apache2/access.log /var/log/httpd/access_log \
|
|
/var/log/apache2/other_vhosts_access.log \
|
|
/var/log/apache2/error.log /var/log/httpd/error_log; do
|
|
[ -s "$_p" ] && _pats="$_pats $_p"
|
|
done
|
|
# Nichts gefunden? Dann die CustomLog-Direktive befragen (verlaesslichste
|
|
# Quelle bei exotischen Setups) — ${APACHE_LOG_DIR} wird aufgeloest.
|
|
if [ -z "$_pats" ]; then
|
|
_cl_dir="$(grep -rhoE '^[[:space:]]*CustomLog[[:space:]]+(\S+|"[^"]+")' \
|
|
/etc/apache2/ /etc/httpd/ /etc/apache2/sites-enabled/ 2>/dev/null \
|
|
| sed -E 's/^[[:space:]]*CustomLog[[:space:]]+//; s/^"//; s/"$//' \
|
|
| grep -v '^|' | grep -v '^/dev/' | sort -u)"
|
|
for _p in $_cl_dir; do
|
|
_p="$(printf '%s' "$_p" | sed "s#\${APACHE_LOG_DIR}#/var/log/apache2#g")"
|
|
[ -r "$_p" ] && _pats="$_pats $_p"
|
|
done
|
|
fi
|
|
# Letzter Ausweg: breiter Scan der ueblichen Wurzelverzeichnisse.
|
|
if [ -z "$_pats" ]; then
|
|
_pats="$(find /var/log/apache2 /var/log/httpd /home -maxdepth 4 \
|
|
\( -name 'access.log' -o -name 'access_log' \
|
|
-o -name 'error.log' -o -name 'error_log' \) 2>/dev/null \
|
|
| head -200 | tr '\n' ' ')"
|
|
fi
|
|
[ -n "$_pats" ] && APACHE_LOG="$(printf '%s' "$_pats" | sed 's/^ *//; s/ *$//')"
|
|
[ -n "$APACHE_LOG" ] || APACHE_LOG="/var/log/apache2/access.log"
|
|
fi
|
|
|
|
# APACHE_LOG kann mehrere, leerzeichengetrennte Pfade enthalten -> als
|
|
# TOML-Liste rendern. Achtung: Pfade mit Leerzeichen sind in Apache-Logs
|
|
# ungewoehnlich; wir quoten jeden Eintrag einzeln.
|
|
# APACHE_FILES IMMER berechnen, NICHT nur bei erkanntem Apache.
|
|
# Realer Fehler: bei ROLE=apache ohne Apache-Erkennung (z. B. httpd auf RHEL,
|
|
# oder Apache wurde entfernt) blieb die Variable leer. Die Conf rendert dann zu
|
|
# "files = " — ungueltiges TOML, Telegraf startet nicht mehr, ALLE Metriken aus.
|
|
# Der Guard war die Ursache; die Berechnung selbst ist harmlos.
|
|
APACHE_FILES=""
|
|
if [ "$HAS_APACHE" -eq 1 ] || [ "$ROLE" = "apache" ]; then
|
|
# set -f: Pfadnamen-Expansion abschalten! Sonst ersetzt die Shell die
|
|
# Glob-Muster durch die aktuell vorhandenen Dateien — die Conf enthielte
|
|
# feste Einzelpfade und jede NEUE Domain fiele heraus, bis der Installer
|
|
# erneut laeuft. Wir wollen die Muster in der Conf, Telegraf loest sie bei
|
|
# jedem Lauf selbst auf.
|
|
# TRENNUNG access/error — wichtig fuer die Metriken:
|
|
# Der Grok-Parser versteht nur das ACCESS-Format
|
|
# IP ident auth [HTTPDATE] "VERB REQ" CODE BYTES
|
|
# Eine Error-Zeile sieht anders aus:
|
|
# [Mon Sep 14 00:10:01.123456 2026] [core:error] [pid 9] AH00124: ...
|
|
# Laeuft sie durch den Access-Parser, entstehen keine Metriken (Muster passt
|
|
# nicht) — schlimmer: der Aggregator zaehlt sie in Gruppen mit, die es nicht
|
|
# gibt. Deshalb bekommt der Access-Input nur Access-Pfade, und die Error-Logs
|
|
# gehen ueber einen eigenen Input roh nach Loki.
|
|
set -f
|
|
for _p in $APACHE_LOG; do
|
|
case "$_p" in
|
|
*error*|*Error*)
|
|
APACHE_ERROR_FILES="${APACHE_ERROR_FILES:+$APACHE_ERROR_FILES, }\"$_p\"" ;;
|
|
*)
|
|
APACHE_FILES="${APACHE_FILES:+$APACHE_FILES, }\"$_p\"" ;;
|
|
esac
|
|
done
|
|
set +f
|
|
[ -n "$APACHE_FILES" ] || APACHE_FILES='"/var/log/apache2/access.log"'
|
|
APACHE_ERROR_FILES="[${APACHE_ERROR_FILES:-\"/var/log/apache2/error.log\"}]"
|
|
export APACHE_ERROR_FILES
|
|
APACHE_FILES="[$APACHE_FILES]"
|
|
fi
|
|
# Sicherheitsnetz: die Variable MUSS nicht-leer sein, bevor apache.conf gerendert
|
|
# wird. Ein leerer Wert erzeugt ungueltiges TOML und kostet die ganze Node.
|
|
[ -n "${APACHE_FILES:-}" ] || APACHE_FILES='["/var/log/apache2/access.log"]'
|
|
export APACHE_FILES
|
|
if [ "$ROLE" = "auto" ]; then
|
|
ROLE="none"
|
|
[ "$IS_PVE" -eq 1 ] && ROLE="proxmox"
|
|
fi
|
|
log "Node=$NODE_NAME OS=$OS_ID Arch=$ARCH Rolle=$ROLE Docker=$HAS_DOCKER Apache=$HAS_APACHE GPU=$GPU Collector=$COLLECTOR"
|
|
|
|
# --------------------------------------------------------------------------
|
|
# Erreichbarkeit des Collectors (NetBird Lazy Connection: erst anklopfen)
|
|
# --------------------------------------------------------------------------
|
|
if command -v curl >/dev/null; then
|
|
HOST_OF_URL="$(printf '%s' "$PROM_URL" | sed -E 's#^https?://([^/:]+).*#\1#')"
|
|
ping -c1 -W2 "$HOST_OF_URL" >/dev/null 2>&1 || true # NetBird Lazy Connection wecken
|
|
if curl -fsS -m 10 -H "Authorization: Bearer $TELEGRAF_TOKEN" "${PROM_URL%/api/v1/write}/-/ready" >/dev/null 2>&1; then
|
|
log "Collector erreichbar (auth ok): $PROM_URL"
|
|
else
|
|
log "WARNUNG: $PROM_URL nicht erreichbar oder Token falsch — Installation läuft weiter, Telegraf puffert und retried."
|
|
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
|
|
# --------------------------------------------------------------------------
|
|
install_apt() {
|
|
# ZWEITE SCHUTZSCHICHT gegen den stdin-Fraß:
|
|
# `needrestart` (Ubuntu-Standard) liest stdin und meldet
|
|
# "Scanning processes... / Scanning linux images...". Mit NEEDRESTART_MODE=a
|
|
# laeuft es nicht-interaktiv, und die apt-Optionen halten dpkg davon ab,
|
|
# Prompts zu stellen. Der Re-Exec oben schuetzt die Shell — diese Zeile
|
|
# schuetzt zusaetzlich den Installer-Ablauf selbst.
|
|
export NEEDRESTART_MODE=a
|
|
export DEBIAN_FRONTEND=noninteractive
|
|
APT_OPTS="-y -qq -o Dpkg::Options::=--force-confdef -o Dpkg::Options::=--force-confold"
|
|
command -v gpg >/dev/null || { apt-get update -qq; apt-get install $APT_OPTS gnupg >/dev/null; }
|
|
command -v curl >/dev/null || apt-get install $APT_OPTS curl >/dev/null
|
|
mkdir -p /etc/apt/keyrings
|
|
curl -fsSL -m 30 --connect-timeout 10 https://repos.influxdata.com/influxdata-archive.key | gpg --dearmor --yes -o /etc/apt/keyrings/influxdata-archive.gpg
|
|
echo "deb [signed-by=/etc/apt/keyrings/influxdata-archive.gpg] https://repos.influxdata.com/debian stable main" > /etc/apt/sources.list.d/influxdata.list
|
|
apt-get update -qq
|
|
apt-get install $APT_OPTS telegraf >/dev/null
|
|
}
|
|
install_rpm() {
|
|
cat > /etc/yum.repos.d/influxdata.repo <<'EOF'
|
|
[influxdata]
|
|
name = InfluxData Repository - Stable
|
|
baseurl = https://repos.influxdata.com/stable/$basearch/main
|
|
enabled = 1
|
|
gpgcheck = 1
|
|
gpgkey = https://repos.influxdata.com/influxdata-archive.key
|
|
EOF
|
|
# dnf/yum lesen ebenfalls stdin (Prompts, Plugin-Rueckfragen) -> hier mit
|
|
# -y und ohne Assumeyes-Rueckfrage, damit nichts aus der Pipe greift.
|
|
if command -v dnf >/dev/null; then
|
|
dnf install -y -q telegraf < /dev/null
|
|
else
|
|
yum install -y -q telegraf < /dev/null
|
|
fi
|
|
}
|
|
install_static() {
|
|
command -v curl >/dev/null || die "curl fehlt."
|
|
TB="telegraf-${TELEGRAF_VERSION}_linux_${ARCH}.tar.gz"
|
|
log "Statisches Binary $TB …"
|
|
TMP="$(mktemp -d)"
|
|
curl -fsSL -m 120 --connect-timeout 10 "https://dl.influxdata.com/telegraf/releases/$TB" -o "$TMP/t.tgz"
|
|
tar -xzf "$TMP/t.tgz" -C "$TMP"
|
|
install -m 0755 "$TMP"/telegraf-*/usr/bin/telegraf /usr/local/bin/telegraf
|
|
rm -rf "$TMP"
|
|
id telegraf >/dev/null 2>&1 || useradd -r -s /usr/sbin/nologin -d /etc/telegraf telegraf 2>/dev/null || adduser -S -D -H -s /sbin/nologin telegraf
|
|
if command -v rc-update >/dev/null; then
|
|
cat > /etc/init.d/telegraf <<'EOF'
|
|
#!/sbin/openrc-run
|
|
description="Telegraf"
|
|
command=/usr/local/bin/telegraf
|
|
command_args="--config /etc/telegraf/telegraf.conf --config-directory /etc/telegraf/telegraf.d"
|
|
command_user=telegraf
|
|
command_background=true
|
|
pidfile=/run/telegraf.pid
|
|
start_pre() {
|
|
# Nur auswerten, wenn die Datei syntaktisch heil ist — sonst startet der
|
|
# Dienst gar nicht (unquoted Werte mit Leerzeichen brechen das Sourcing).
|
|
if [ -r /etc/default/telegraf ] && sh -n /etc/default/telegraf 2>/dev/null; then
|
|
set -a; . /etc/default/telegraf; set +a
|
|
fi
|
|
}
|
|
depend() { need net; }
|
|
EOF
|
|
chmod +x /etc/init.d/telegraf
|
|
return
|
|
fi
|
|
mkdir -p /etc/systemd/system
|
|
cat > /etc/systemd/system/telegraf.service <<'EOF'
|
|
[Unit]
|
|
Description=Telegraf
|
|
After=network-online.target
|
|
Wants=network-online.target
|
|
[Service]
|
|
User=telegraf
|
|
EnvironmentFile=-/etc/default/telegraf
|
|
ExecStart=/usr/local/bin/telegraf --config /etc/telegraf/telegraf.conf --config-directory /etc/telegraf/telegraf.d
|
|
Restart=on-failure
|
|
RestartSec=5s
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
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 ;;
|
|
rhel|centos|rocky|almalinux|fedora|ol) install_rpm ;;
|
|
alpine) apk add --no-cache -q curl ca-certificates < /dev/null; install_static ;;
|
|
*) if command -v apt-get >/dev/null; then install_apt
|
|
elif command -v dnf >/dev/null || command -v yum >/dev/null; then install_rpm
|
|
else install_static; fi ;;
|
|
esac
|
|
fi
|
|
|
|
# --------------------------------------------------------------------------
|
|
# Log-Leserechte fuer den Dienst-Benutzer
|
|
# --------------------------------------------------------------------------
|
|
# Zwei verschiedene Rechte-Welten bei Apache-Logs:
|
|
# /var/log/apache2/... root:adm 0640 -> usermod -aG adm genuegt
|
|
# /home/users/<u>/logs/... <u>:<u> 0640 -> adm hilft NICHT
|
|
# KeyHelp/Plesk legen die VHost-Logs in den User-Homes ab (auf x22: 64 von 84
|
|
# Pfaden waren fuer 'telegraf' unlesbar). inputs.tail meldet das NICHT — es
|
|
# liefert einfach nichts, und der Node sieht "aktiv" aus.
|
|
# Loesung: ein ACL fuer den Dienst-Benutzer, rekursiv und vererbbar. Damit
|
|
# bleibt der Dienst im eingeschraenkten Konto (kein root noetig) und neue
|
|
# Domain-Ordner erben das Recht automatisch.
|
|
grant_apache_log_access() {
|
|
[ "$HAS_APACHE" -eq 1 ] || return 0
|
|
# Fortschritt melden: ohne diese Zeile sah der Lauf wie ein Haenger aus,
|
|
# weil zwischen "Telegraf bereits installiert" und der naechsten Meldung
|
|
# ein apt-Aufruf mit Netzwerkzugriff liegt (kann bis zu 3 Minuten dauern).
|
|
log "Log-Leserechte: pruefe/ergaenze ACL fuer 'telegraf' (kann etwas dauern) …"
|
|
_u="telegraf"
|
|
id "$_u" >/dev/null 2>&1 || return 0
|
|
if ! command -v setfacl >/dev/null 2>&1; then
|
|
# acl-Paket nachziehen, sonst ist die Rechtevergabe nicht moeglich.
|
|
# Alle Paketmanager mit </dev/null: sie duerfen nichts aus stdin lesen.
|
|
# `timeout` ist PFLICHT: ohne Paketlisten kann apt in eine Rueckfrage laufen
|
|
# und unbegrenzt warten — der Installer haengt dann nach der letzten
|
|
# Erfolgsmeldung, ohne Fehler. Real passiert (x14): Abbruch per ^C.
|
|
if command -v apt-get >/dev/null; then
|
|
apt-get update -qq </dev/null >/dev/null 2>&1 || true
|
|
timeout 180 env NEEDRESTART_MODE=a DEBIAN_FRONTEND=noninteractive \
|
|
apt-get install -y -qq acl </dev/null >/dev/null 2>&1 || true
|
|
elif command -v dnf >/dev/null; then
|
|
timeout 180 dnf install -y -q acl </dev/null >/dev/null 2>&1 || true
|
|
elif command -v yum >/dev/null; then
|
|
timeout 180 yum install -y -q acl </dev/null >/dev/null 2>&1 || true
|
|
elif command -v apk >/dev/null; then
|
|
timeout 180 apk add --no-cache -q acl </dev/null >/dev/null 2>&1 || true
|
|
fi
|
|
fi
|
|
if ! command -v setfacl >/dev/null 2>&1; then
|
|
log "HINWEIS: setfacl fehlt — Apache-Logs in User-Homes bleiben evtl. unlesbar."
|
|
log " Pruefen mit: sh install.sh --diagnose"
|
|
return 0
|
|
fi
|
|
|
|
# 1) Verzeichnisse aus der aktiven Conf ermitteln (nur die Wurzel, dann
|
|
# rekursiv — das haelt die ACL-Zahl klein).
|
|
_roots=""
|
|
for _f in $(sed -n 's/^[[:space:]]*files = \[\(.*\)\].*/\1/p' \
|
|
/etc/telegraf/telegraf.d/apache.conf 2>/dev/null | tr -d '"' | tr ',' ' '); do
|
|
case "$_f" in
|
|
*/\**) _f="${_f%%/\**}" ;; # /a/b/** -> /a/b
|
|
*/*) _f="${_f%/*}" ;; # /a/b/*/x -> /a/b/*
|
|
esac
|
|
case "$_f" in
|
|
*/\*|*/\*/*) _f="${_f%%\**}" ;; # Glob-Rest abschneiden
|
|
esac
|
|
_f="${_f%/}"
|
|
[ -d "$_f" ] && _roots="$_roots $_f"
|
|
done
|
|
# Panel-typische Wurzeln direkt mitnehmen (auch wenn die Conf sie globt)
|
|
for _d in /home/users /home/*/logs /var/www/vhosts /usr/local/apache/domlogs; do
|
|
[ -d "$_d" ] && _roots="$_roots $_d"
|
|
done
|
|
[ -n "$_roots" ] || return 0
|
|
|
|
_n=0
|
|
for _r in $_roots; do
|
|
# Durchgangsrecht (x) auf die Elternverzeichnisse, Leserecht (r) auf die
|
|
# Dateien: rX vergibt x nur fuer Verzeichnisse.
|
|
setfacl -R -m "u:$_u:rX" "$_r" 2>/dev/null && _n=$((_n+1))
|
|
# Neu angelegte Dateien/Ordner erben das Recht (default-ACL nur fuer dirs).
|
|
if [ -d "$_r" ]; then
|
|
setfacl -R -d -m "u:$_u:rX" "$_r" 2>/dev/null || true
|
|
fi
|
|
done
|
|
[ "$_n" -gt 0 ] && log "Log-Leserechte gesetzt (ACL fuer '$_u') auf $_n Wurzel(n)."
|
|
|
|
# 2) Gegentest: eine echte Datei als Dienst-Benutzer lesen.
|
|
_testfile=""
|
|
for _f in $(sed -n 's/^[[:space:]]*files = \[\(.*\)\].*/\1/p' \
|
|
/etc/telegraf/telegraf.d/apache.conf 2>/dev/null | tr -d '"' | tr ',' ' '); do
|
|
# shellcheck disable=SC2086
|
|
_cand="$(ls $_f 2>/dev/null | head -1)"
|
|
if [ -n "$_cand" ] && [ -s "$_cand" ]; then _testfile="$_cand"; break; fi
|
|
done
|
|
if [ -n "$_testfile" ]; then
|
|
if su -s /bin/sh "$_u" -c "head -c 1 \"$_testfile\" >/dev/null 2>&1"; then
|
|
log "Gegentest: '$_u' kann Apache-Logs lesen ($_testfile)."
|
|
else
|
|
log "WARNUNG: '$_u' kann $_testfile nicht lesen — --diagnose ausfuehren."
|
|
fi
|
|
fi
|
|
}
|
|
|
|
# --------------------------------------------------------------------------
|
|
# Konfiguration
|
|
# --------------------------------------------------------------------------
|
|
# Proxmox-Parameter VOR dem Schreiben der Konfiguration ermitteln
|
|
if [ "$ROLE" = "proxmox" ]; then
|
|
[ -n "$PVE_NODE" ] || PVE_NODE="$(pvesh get /nodes --output-format json 2>/dev/null | sed -n 's/.*"node":"\([^"]*\)".*/\1/p' | head -1)"
|
|
[ -n "$PVE_NODE" ] || PVE_NODE="$NODE_NAME"
|
|
[ -n "$PVE_URL" ] || PVE_URL="https://127.0.0.1:8006/api2/json"
|
|
log "Proxmox: node_name=$PVE_NODE base_url=$PVE_URL"
|
|
fi
|
|
|
|
mkdir -p /etc/telegraf/telegraf.d /etc/default
|
|
umask 077
|
|
cat > /etc/default/telegraf <<EOF
|
|
NODE_NAME=$NODE_NAME
|
|
# Die InfluxData-Unit nutzt \$TELEGRAF_OPTS in ExecStart. Ohne diesen Wert
|
|
# warnt systemd bei jedem Start "Referenced but unset environment variable".
|
|
# Explizit leer setzen = Warnung weg, Verhalten unveraendert.
|
|
TELEGRAF_OPTS=
|
|
|
|
# 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
|
|
TELEGRAF_TOKEN=$TELEGRAF_TOKEN
|
|
PVE_TOKEN=$PVE_TOKEN
|
|
PVE_NODE=$PVE_NODE
|
|
PVE_URL=$PVE_URL
|
|
# WICHTIG: Diese Datei wird per ". /etc/default/telegraf" GESOURCT. Werte ohne
|
|
# Anfuehrungszeichen brechen bei Leerzeichen oder Sonderzeichen: bei mehreren
|
|
# Logpfaden versucht die Shell, den zweiten Pfad als Befehl auszufuehren
|
|
# ("...access.log: Permission denied"). Eckige Klammern (TOML-Liste) sind im
|
|
# Sourcing sogar Syntaxmuell. Deshalb alles quoten — die Werte werden in der
|
|
# Config nur als String gebraucht, nicht als Liste.
|
|
APACHE_LOG='$APACHE_LOG'
|
|
EOF
|
|
umask 022
|
|
|
|
# Jeder Download MIT Timeout: ohne -m wartet curl unbegrenzt, wenn das Netz
|
|
# haengt (NetBird-Tunnel, DNS). Der Installer bliebe dann nach der letzten
|
|
# Erfolgsmeldung stehen — ohne Fehler, ohne Ende. Genau das passierte auf x14.
|
|
fetch() {
|
|
_tries=3
|
|
while [ "$_tries" -gt 0 ]; do
|
|
if curl -fsSL -m 30 --connect-timeout 10 "$REPO_RAW/$1" -o "$2" 2>/dev/null; then
|
|
return 0
|
|
fi
|
|
_tries=$((_tries - 1))
|
|
[ "$_tries" -gt 0 ] && sleep 2
|
|
done
|
|
die "Download $1 fehlgeschlagen nach 3 Versuchen ($REPO_RAW/$1)."
|
|
}
|
|
|
|
# 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"
|
|
load_defaults
|
|
if command -v envsubst >/dev/null; then
|
|
envsubst '${NODE_NAME} ${PROM_URL} ${LOKI_URL} ${TELEGRAF_TOKEN} ${PVE_TOKEN} ${PVE_NODE} ${PVE_URL} ${APACHE_LOG} ${APACHE_FILES} ${APACHE_ERROR_FILES}'
|
|
else
|
|
subst_vars "$2.tmp" "$2" NODE_NAME PROM_URL LOKI_URL TELEGRAF_TOKEN PVE_TOKEN PVE_NODE PVE_URL APACHE_LOG APACHE_FILES APACHE_ERROR_FILES
|
|
fi
|
|
if grep -q '\${' "$2"; then
|
|
log "WARNUNG: $2 enthaelt noch unaufgeloeste Platzhalter:"
|
|
grep -o '\${[A-Z_]*}' "$2" | sort -u >&2
|
|
fi
|
|
rm -f "$2.tmp"
|
|
}
|
|
fetch_conf telegraf/base.conf /etc/telegraf/telegraf.conf
|
|
# Nur Confs entfernen, die DIESER Installer verwaltet — nicht pauschal alles.
|
|
# Sonst reisst ein Auto-Update fremde oder manuell ergaenzte Confs mit, die
|
|
# jemand bewusst nach /etc/telegraf/telegraf.d/ gelegt hat.
|
|
for _c in docker proxmox apache gpu journal nodeinfo syslog; do
|
|
rm -f "/etc/telegraf/telegraf.d/$_c.conf"
|
|
done
|
|
[ "$HAS_DOCKER" -eq 1 ] && { fetch telegraf/docker.conf /etc/telegraf/telegraf.d/docker.conf; usermod -aG docker telegraf 2>/dev/null || true; }
|
|
case "$ROLE" in
|
|
proxmox) : # pvesh-Weg braucht keinen Token (siehe unten)
|
|
fetch scripts/proxmox-ve.sh /etc/telegraf/proxmox-ve.sh
|
|
chmod 0755 /etc/telegraf/proxmox-ve.sh
|
|
# pvesh-Weg: braucht keinen Token und keine ACL (laeuft als root)
|
|
cat > /etc/telegraf/telegraf.d/proxmox.conf <<'EOF'
|
|
[[inputs.exec]]
|
|
interval = "30s"
|
|
timeout = "25s"
|
|
data_format = "prometheus"
|
|
commands = ["/etc/telegraf/proxmox-ve.sh"]
|
|
EOF
|
|
log "Proxmox: pvesh-Input aktiv (VM/CT-Metriken, kein API-Token noetig)." ;;
|
|
apache) fetch_conf telegraf/apache.conf /etc/telegraf/telegraf.d/apache.conf
|
|
usermod -aG adm telegraf 2>/dev/null || true
|
|
grant_apache_log_access ;;
|
|
docker|none) ;;
|
|
*) die "Unbekannte Rolle: $ROLE" ;;
|
|
esac
|
|
[ "$HAS_APACHE" -eq 1 ] && [ "$ROLE" != "apache" ] && {
|
|
fetch_conf telegraf/apache.conf /etc/telegraf/telegraf.d/apache.conf
|
|
usermod -aG adm telegraf 2>/dev/null || true
|
|
grant_apache_log_access
|
|
}
|
|
|
|
# --- System-Logs (journald) → Loki — nur auf systemd-Systemen ---
|
|
if command -v journalctl >/dev/null 2>&1 && [ -d /run/systemd/system ]; then
|
|
fetch scripts/journal-tail.sh /etc/telegraf/journal-tail.sh
|
|
chmod 0755 /etc/telegraf/journal-tail.sh
|
|
fetch_conf telegraf/journal.conf /etc/telegraf/telegraf.d/journal.conf
|
|
# Zustandsverzeichnis fuer den Journal-Cursor
|
|
mkdir -p /var/lib/telegraf-journal
|
|
if [ "$ROLE" = "proxmox" ]; then
|
|
: # laeuft als root (Drop-in) — voller Journal-Zugriff
|
|
else
|
|
chown telegraf:telegraf /var/lib/telegraf-journal 2>/dev/null || true
|
|
usermod -aG systemd-journal telegraf 2>/dev/null || true
|
|
fi
|
|
log "Journald-Logs aktiv (Warnungen+, inkrementell ueber Cursor)."
|
|
fi
|
|
|
|
# --- Node-Info (LAN-IP, NetBird-IP/FQDN, PVE-URL) — auf jeder Node ---
|
|
fetch scripts/node-info.sh /etc/telegraf/node-info.sh
|
|
chmod 0755 /etc/telegraf/node-info.sh
|
|
cat > /etc/telegraf/telegraf.d/nodeinfo.conf <<'EOF'
|
|
[[inputs.exec]]
|
|
interval = "300s"
|
|
timeout = "25s"
|
|
data_format = "prometheus"
|
|
commands = ["/etc/telegraf/node-info.sh"]
|
|
EOF
|
|
log "Node-Info aktiv (LAN-IP, NetBird-IP/FQDN, PVE-URL)."
|
|
|
|
# --- GPU (nur wenn erkannt) ---
|
|
# Jeder Block wird NUR geschrieben, wenn das jeweilige Werkzeug wirklich da ist.
|
|
# Ein Input ohne Binary laesst Telegraf beim Start hart scheitern -> alle Metriken aus.
|
|
case "$GPU" in
|
|
nvidia)
|
|
cat > /etc/telegraf/telegraf.d/gpu.conf <<'EOF'
|
|
[[inputs.nvidia_smi]]
|
|
timeout = "10s"
|
|
[inputs.nvidia_smi.tagdrop]
|
|
compute_mode = ["*"]
|
|
EOF
|
|
log "NVIDIA-GPU erkannt: inputs.nvidia_smi aktiv."
|
|
;;
|
|
amd)
|
|
fetch scripts/gpu-rocm.sh /etc/telegraf/gpu-rocm.sh
|
|
chmod 0755 /etc/telegraf/gpu-rocm.sh
|
|
# KEIN name_override: das Script liefert die Metriknamen selbst
|
|
# (gpu_utilization_gpu, gpu_temperature_edge, ...). name_override wuerde
|
|
# alle Werte zu "gpu" kollabieren -> in Prometheus nur noch gpu_value.
|
|
# data_format = prometheus: mit "influx" haengt Telegraf "_value" an den Namen.
|
|
cat > /etc/telegraf/telegraf.d/gpu.conf <<'EOF'
|
|
[[inputs.exec]]
|
|
interval = "30s"
|
|
timeout = "20s"
|
|
data_format = "prometheus"
|
|
commands = ["/etc/telegraf/gpu-rocm.sh"]
|
|
EOF
|
|
log "AMD-GPU erkannt: rocm-smi-exec-Input aktiv."
|
|
;;
|
|
intel)
|
|
# Bewusst KEIN GPU-Input: intel_gpu_top liefert kein Prometheus/Influx-Format
|
|
# und ein nvidia_smi-Block ohne nvidia-smi wuerde Telegraf killen.
|
|
log "Intel-GPU (/dev/dri) erkannt: kein GPU-Input aktiviert (intel_gpu_top wird nicht erfasst)."
|
|
;;
|
|
*) : ;;
|
|
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
|
|
# --------------------------------------------------------------------------
|
|
# WICHTIG: NICHT mit --input-filter pruefen! Telegraf validiert dann nur die
|
|
# gefilterten Plugins und ueberspringt die uebrigen Konfigdateien. Ein Fehler in
|
|
# telegraf.d/apache.conf (z.B. ein ungueltiges Feld) lief damit durch, der
|
|
# Installer meldete "OK", und erst der Dienststart scheiterte:
|
|
# Job for telegraf.service failed
|
|
# Ohne Filter werden ALLE Dateien geparst — genau wie beim Dienststart. Das ist
|
|
# der einzige Test, der den Startfehler wirklich verhindert.
|
|
TG="$(command -v telegraf || echo /usr/local/bin/telegraf)"
|
|
load_defaults
|
|
|
|
conf_test() {
|
|
_out="$("$TG" --config /etc/telegraf/telegraf.conf \
|
|
--config-directory /etc/telegraf/telegraf.d --test --test-wait 1 2>&1)"
|
|
_rc=$?
|
|
# Nur echte Konfigurationsfehler zaehlen. Ein fehlendes Input-Binary
|
|
# (nvidia-smi) erscheint erst beim Start als E!, nicht beim Parsen — und
|
|
# Sammel-Warnungen wie die DeprecationNotice sind harmlos.
|
|
if [ "$_rc" -ne 0 ] || printf '%s' "$_out" | grep -q '^.*E!.*loading config file'; then
|
|
printf '%s\n' "$_out" | grep -E 'E!' | head -5 >&2
|
|
return 1
|
|
fi
|
|
return 0
|
|
}
|
|
|
|
if ! conf_test; 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
|
|
conf_test || die "Konfiguration auch nach Rollback ungültig — telegraf --test prüfen."
|
|
log "Rollback erfolgreich, alte Konfiguration aktiv."
|
|
else
|
|
die "Konfiguration ungültig — siehe Meldung oben. Einzelne Datei pruefen mit: telegraf --config /etc/telegraf/telegraf.conf --config-directory /etc/telegraf/telegraf.d --test"
|
|
fi
|
|
fi
|
|
|
|
# --------------------------------------------------------------------------
|
|
# Dienst
|
|
# --------------------------------------------------------------------------
|
|
# Proxmox-Rolle: pvesh verlangt root. Der InfluxData-Dienst laeuft als User
|
|
# "telegraf" -> das Script liefert dann still nichts. Drop-in auf root.
|
|
if [ "$ROLE" = "proxmox" ] && [ -d /etc/systemd/system ]; then
|
|
mkdir -p /etc/systemd/system/telegraf.service.d
|
|
cat > /etc/systemd/system/telegraf.service.d/10-proxmox-root.conf <<'EOF'
|
|
# pvesh (VM/CT-Metriken) erfordert root-Rechte.
|
|
[Service]
|
|
User=root
|
|
Group=root
|
|
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
|
|
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
|
|
# Haeufigste Ursache: ein aktivierter Input, dessen Binary fehlt
|
|
# (z.B. nvidia_smi ohne nvidia-smi). GPU-Conf verwerfen und erneut versuchen.
|
|
if [ -f /etc/telegraf/telegraf.d/gpu.conf ]; then
|
|
log "Start fehlgeschlagen — entferne GPU-Conf und versuche erneut."
|
|
rm -f /etc/telegraf/telegraf.d/gpu.conf
|
|
systemctl reset-failed telegraf 2>/dev/null || true
|
|
systemctl restart telegraf
|
|
sleep 3
|
|
fi
|
|
systemctl is-active --quiet telegraf || die "telegraf läuft nicht. journalctl -u telegraf -n 30 prüfen."
|
|
log "WARNUNG: Telegraf läuft, aber ohne GPU-Metriken (Input-Binary fehlte)."
|
|
fi
|
|
elif command -v systemctl >/dev/null; then
|
|
log "HINWEIS: systemd nicht aktiv (Container/Chroot) — Dienst wird beim nächsten Boot gestartet (enabled)."
|
|
systemctl enable telegraf >/dev/null 2>&1 || true
|
|
elif command -v rc-update >/dev/null; then
|
|
rc-update add telegraf default >/dev/null 2>&1 || true
|
|
rc-service telegraf restart >/dev/null 2>&1 || log "HINWEIS: OpenRC nicht aktiv (Container?) — Dienst beim nächsten Boot."
|
|
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)"
|