#!/usr/bin/env bash # ========================================= # HX-KI · SERVER-ANALYSE v1 (READ-ONLY) # - Generalisierbar für alle HX-KI-Server # - Architektur + Runtime # - KEINE Löschungen, KEINE Änderungen # - Output: /opt/hx-ki/inventory/hxki_server_analyse__.txt # ========================================= set -euo pipefail HOST="$(hostname -f 2>/dev/null || hostname)" NOW="$(date +%Y%m%d-%H%M%S)" REPORT_DIR="/opt/hx-ki/inventory" REPORT="${REPORT_DIR}/hxki_server_analyse_${HOST}_${NOW}.txt" mkdir -p "${REPORT_DIR}" log() { echo "$@" | tee -a "${REPORT}" } sep() { log log "-----------------------------------------" } log "=========================================" log " HX-KI · SERVER-ANALYSE v1" log " Host: ${HOST}" log " Datum: ${NOW}" log "=========================================" log # 1) SYSTEM / OS / KERNEL log "[1] SYSTEM · OS · KERNEL" log "-----------------------------------------" log "uname -a:" uname -a 2>&1 | tee -a "${REPORT}" log log "/etc/os-release (relevant):" if [ -f /etc/os-release ]; then grep -E '^(PRETTY_NAME|NAME|VERSION)=' /etc/os-release 2>/dev/null | tee -a "${REPORT}" || cat /etc/os-release | tee -a "${REPORT}" else log " /etc/os-release nicht gefunden." fi log log "uptime:" uptime 2>&1 | tee -a "${REPORT}" sep # 2) CPU / RAM / STORAGE log "[2] HARDWARE · SPEICHER · PLATZ" log "-----------------------------------------" log "CPU:" lscpu 2>/dev/null | sed -n '1,10p' | tee -a "${REPORT}" || log " lscpu nicht verfügbar." log log "RAM (free -h):" free -h 2>/dev/null | tee -a "${REPORT}" || log " free nicht verfügbar." log log "Storage (df -h / und /opt /data, falls vorhanden):" df -h / 2>/dev/null | tee -a "${REPORT}" || log " df / fehlgeschlagen." [ -d /opt ] && df -h /opt 2>/dev/null | tee -a "${REPORT}" || true [ -d /data ] && df -h /data 2>/dev/null | tee -a "${REPORT}" || true sep # 3) NETZWERK / OFFENE PORTS (Architektur-Sicht) log "[3] NETZWERK · INTERFACES · PORTS" log "-----------------------------------------" log "IP / Interfaces (ip -brief addr):" ip -brief addr 2>/dev/null | tee -a "${REPORT}" || log " ip nicht verfügbar." log log "Routen (ip route):" ip route 2>/dev/null | tee -a "${REPORT}" || log " ip route nicht verfügbar." log log "Offene TCP/UDP-Ports (ss -tulpen, Kurzform):" ss -tulpen 2>/dev/null | tee -a "${REPORT}" || log " ss nicht verfügbar." sep # 4) DOCKER · ARCHITEKTUR + RUNTIME log "[4] DOCKER · ARCHITEKTUR + RUNTIME" log "-----------------------------------------" if command -v docker >/dev/null 2>&1; then log "docker version (Kurzinfo):" docker version --format 'Client: {{.Client.Version}} · Server: {{.Server.Version}}' 2>/dev/null | tee -a "${REPORT}" || log " docker version fehlgeschlagen." log log "Laufende Container (Names, Image, Command, Status, Ports):" docker ps --format "table {{.Names}}\t{{.Image}}\t{{.Command}}\t{{.Status}}\t{{.Ports}}" 2>/dev/null | tee -a "${REPORT}" || log " docker ps fehlgeschlagen." log log "Alle Container (inkl. exited):" docker ps -a --format "table {{.Names}}\t{{.Image}}\t{{.Status}}" 2>/dev/null | tee -a "${REPORT}" || log " docker ps -a fehlgeschlagen." log log "Docker-Networks:" docker network ls 2>/dev/null | tee -a "${REPORT}" || log " docker network ls fehlgeschlagen." log log "Docker-Volumes:" docker volume ls 2>/dev/null | tee -a "${REPORT}" || log " docker volume ls fehlgeschlagen." log log "Docker Images (Kurzliste):" docker images --format "table {{.Repository}}\t{{.Tag}}\t{{.Size}}" 2>/dev/null | tee -a "${REPORT}" || log " docker images fehlgeschlagen." log # 4a) ARCHITEKTUR-METADATEN JE CONTAINER log "Container-Architektur-Details (Compose-Labels, Volumes, Networks):" for cname in $(docker ps --format '{{.Names}}' 2>/dev/null); do log log " >>> Container: ${cname}" docker inspect "${cname}" \ --format ' Labels: {{json .Config.Labels}}' 2>/dev/null | tee -a "${REPORT}" || log " Labels konnten nicht gelesen werden." docker inspect "${cname}" \ --format ' Mounts: {{json .Mounts}}' 2>/dev/null | tee -a "${REPORT}" || log " Mounts konnten nicht gelesen werden." docker inspect "${cname}" \ --format ' Networks: {{json .NetworkSettings.Networks}}' 2>/dev/null | tee -a "${REPORT}" || log " Networks konnten nicht gelesen werden." done else log "Docker ist nicht installiert oder nicht im PATH." fi sep # 5) /opt · ARCHITEKTURBAUM (HX-KI) log "[5] /opt · ARCHITEKTURBAUM" log "-----------------------------------------" if [ -d /opt ]; then log "ls -al /opt:" ls -al /opt 2>&1 | tee -a "${REPORT}" log if [ -d /opt/hx-ki ]; then log "ls -al /opt/hx-ki (Top-Level):" ls -al /opt/hx-ki 2>&1 | tee -a "${REPORT}" log log "/opt/hx-ki Unterstruktur (maxdepth 3):" find /opt/hx-ki -maxdepth 3 -type d 2>/dev/null | tee -a "${REPORT}" else log "/opt/hx-ki existiert nicht." fi else log "/opt existiert nicht." fi sep # 6) /data · WORKSPACE-EBENE log "[6] /data · WORKSPACE" log "-----------------------------------------" if [ -d /data ]; then log "ls -al /data:" ls -al /data 2>&1 | tee -a "${REPORT}" log # nur eine Ebene tiefer auflisten, um nicht zu fluten for d in /data/*; do [ -d "$d" ] || continue log "Inhalt von $(basename "$d") (maxdepth 2):" find "$d" -maxdepth 2 -type d -o -maxdepth 1 -type f 2>/dev/null | tee -a "${REPORT}" log done else log "/data existiert nicht." fi sep # 7) DOCKER-COMPOSE / BAUPLÄNE log "[7] DOCKER-COMPOSE · BAUPLÄNE" log "-----------------------------------------" if [ -d /opt ]; then log "Gefundene docker-compose.yml / compose.yml unter /opt (maxdepth 6):" find /opt -maxdepth 6 -type f \( -name "docker-compose.yml" -o -name "compose.yml" \) 2>/dev/null | tee -a "${REPORT}" || log " keine Compose-Dateien gefunden." log # Optional: ersten Zeilen jeder Compose-Datei (Architekturüberblick) while IFS= read -r f; do [ -f "$f" ] || continue log ">>> Auszug aus: $f" sed -n '1,40p' "$f" 2>/dev/null | tee -a "${REPORT}" log done < <(find /opt -maxdepth 4 -type f \( -name "docker-compose.yml" -o -name "compose.yml" \) 2>/dev/null || true) else log "kein /opt → keine Compose-Suche." fi sep # 8) ENV-FILES / KONFIG (ohne Inhalte zu leaken, nur Pfade) log "[8] ENV-FILES / KONFIG-PFADE" log "-----------------------------------------" if [ -d /opt/hx-ki ]; then log "ENV-ähnliche Dateien unter /opt/hx-ki (nur Pfade, kein Inhalt):" find /opt/hx-ki -maxdepth 4 -type f \( -name ".env" -o -name "*.env" -o -name "*.env.local" \) 2>/dev/null | tee -a "${REPORT}" || log " keine ENV-Dateien gefunden." else log "/opt/hx-ki existiert nicht → keine ENV-Suche." fi sep # 9) POSTGRES / DATENBANK-ÜBERSICHT (wenn Container vorhanden) log "[9] POSTGRES · DATENBANK-ÜBERSICHT" log "-----------------------------------------" if command -v docker >/dev/null 2>&1; then # versuche, einen Postgres-Container zu finden (heuristisch) PG_CONT="$(docker ps --format '{{.Names}} {{.Image}}' 2>/dev/null | grep -Ei 'postgres' | head -n1 | awk '{print $1}')" if [ -n "${PG_CONT}" ]; then log "Gefundener Postgres-Container: ${PG_CONT}" # env dumpen (aber ohne Passwort-Werte im Klartext, nur Keys sichtbar machen) log "Postgres-Env (nur Keys):" docker inspect "${PG_CONT}" --format '{{range .Config.Env}}{{println .}}{{end}}' 2>/dev/null \ | sed 's/=.*/=***MASKIERT***/' | tee -a "${REPORT}" || log " Env nicht lesbar." # versuche, DB-Liste zu holen (generisch) log log "Datenbanken in dieser Instanz (psql -l, falls möglich):" docker exec -it "${PG_CONT}" psql -U postgres -c "\l" 2>/dev/null | tee -a "${REPORT}" || \ docker exec -it "${PG_CONT}" psql -U hxki -c "\l" 2>/dev/null | tee -a "${REPORT}" || \ log " psql -l konnte nicht generisch ausgeführt werden (User/Pass unbekannt)." else log "Kein laufender Postgres-Container gefunden." fi else log "Docker nicht verfügbar → keine Postgres-Analyse." fi sep log "=========================================" log " ENDE · SERVER-ANALYSE v1" log " Report: ${REPORT}" log "========================================="