Hallo,
Ich hab mir mal gedacht ich teil mein Script mit euch.
Ich übe zzt. Die Shell Script entwicklung in meiner ausbildung und dachte mir ich baue für meine Firma ein Monitoring Script welches den Aktuellen Speicherplatz des Backup Datastores Täglich via Cronjob an die Ticket E-Mail schickt.
Aktuell versuche ich in die Status mail die Prognose von Proxmox mit einzubringen
Sprich eine Trend-Analyse für "Geschätzt Voll"
Leider scheitere ich daran noch aktuell ein wenig, Aktuell bekomme ich ständig die info
Dass Script hänge ich in nem Code-Block an, Vielleicht hat ja jemand ne idee wie ich die Prognose dierekt mit einem der von der Proxmox API Bereitgestellten GET Parameter,
Die Aktuelle lösung bringt leider kein Erfolg.
Ich bedanke mich schonmal im Vorraus für jede hilfe.
#LearningByDoing
PS: für Dieses Script wurde Kaum bis keine KI genutzt.
Bedeutet ich nutze VS-Code zum Programmieren welches die automatische einrückung für mich vornimmt, aber nicht beim Code Schreiben allgemein hilf..
Ich lerne durch meine Fehler und suche mir fast alles durch Tutorials zusammen.
MFG
Ich hab mir mal gedacht ich teil mein Script mit euch.
Ich übe zzt. Die Shell Script entwicklung in meiner ausbildung und dachte mir ich baue für meine Firma ein Monitoring Script welches den Aktuellen Speicherplatz des Backup Datastores Täglich via Cronjob an die Ticket E-Mail schickt.
Aktuell versuche ich in die Status mail die Prognose von Proxmox mit einzubringen
Sprich eine Trend-Analyse für "Geschätzt Voll"
Leider scheitere ich daran noch aktuell ein wenig, Aktuell bekomme ich ständig die info
Code:
Trend & Prognose:
-----------------
Wachstum: Speicher wächst aktuell nicht.
Voraussichtlich voll in: Unbekannt (zu wenig Daten)
Dass Script hänge ich in nem Code-Block an, Vielleicht hat ja jemand ne idee wie ich die Prognose dierekt mit einem der von der Proxmox API Bereitgestellten GET Parameter,
Die Aktuelle lösung bringt leider kein Erfolg.
Bash:
#!/usr/bin/env bash
# pbs-datastore-monitor.sh
# Überwacht den Speicherplatz eines PBS Datastores über die lokale API.
# Beinhaltet automatische 14-Tage Log-Rotation und Fehlerberichterstattung.
#
# Usage:
# ./pbs-datastore-monitor.sh -d <Datastore> -t <To-Mail> [-f <From-Mail>] [-w <Threshold>] [-r]
set -euo pipefail
export LC_ALL=C
export PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
# Standardwerte
DATASTORE="local"
NOTIFY_MAIL="ticket@"
MAIL_FROM="pve-cluster@"
WARN_THRESHOLD_PERCENT=20
MODE="check"
UNIT="pbs" # Basis 1000 wie PBS GUI
# Argumente parsen
while [[ "$#" -gt 0 ]]; do
case $1 in
-d|--datastore) DATASTORE="$2"; shift ;;
-t|--to) NOTIFY_MAIL="$2"; shift ;;
-f|--from) MAIL_FROM="$2"; shift ;;
-w|--warn) WARN_THRESHOLD_PERCENT="$2"; shift ;;
-r|--report) MODE="report" ;;
-h|--help)
echo "Usage: $0 -d <Datastore> -t <To-Mail> [-f <From-Mail>] [-w <Warn-Threshold-%>] [-r|--report]"
exit 0
;;
*) echo "Unbekannter Parameter: $1" >&2; exit 1 ;;
esac
shift
done
# Frühe Validierung (bevor Dateien angelegt werden)
if [ -z "${DATASTORE}" ] || [ -z "${NOTIFY_MAIL}" ]; then
echo "Fehler: -d <Datastore> und -t <To-Mail> sind zwingend erforderlich." >&2
exit 1
fi
STATE_DIR="/var/lib/pbs-space-monitor"
STATE_FILE="${STATE_DIR}/state_${DATASTORE}.txt"
LOG_FILE="${STATE_DIR}/monitor_${DATASTORE}.log"
LOG_CYCLE_FILE="${STATE_DIR}/cycle_${DATASTORE}.txt"
PIVOT_HOST="$(hostname -s)"
mkdir -p "${STATE_DIR}"
# --- LOGGING FUNKTION ---
log() {
local level="$1"
local msg="$2"
local ts="$(date '+%Y-%m-%d %H:%M:%S')"
local log_line="${ts} [${level}] ${msg}"
# Ins Logfile schreiben
echo "${log_line}" >> "${LOG_FILE}"
# Auf die Konsole ausgeben
if [ "${level}" = "ERROR" ]; then
echo "${log_line}" >&2
else
echo "${log_line}"
fi
}
# --- MAIL FUNKTION ---
send_mail() {
local subject="$1"
local body="$2"
if command -v sendmail >/dev/null 2>&1; then
local sendmail_cmd=(sendmail)
[ -n "${MAIL_FROM}" ] && sendmail_cmd+=("-f" "${MAIL_FROM}")
sendmail_cmd+=("${NOTIFY_MAIL}")
if ! {
[ -n "${MAIL_FROM}" ] && echo "From: ${MAIL_FROM}"
echo "To: ${NOTIFY_MAIL}"
echo "Subject: ${subject}"
echo ""
echo -e "${body}"
} | "${sendmail_cmd[@]}"; then
log "ERROR" "E-Mail Versand via sendmail fehlgeschlagen."
exit 1
fi
elif command -v mail >/dev/null 2>&1; then
if [ -n "${MAIL_FROM}" ]; then
if ! echo -e "${body}" | mail -a "From: ${MAIL_FROM}" -s "${subject}" "${NOTIFY_MAIL}"; then
log "ERROR" "E-Mail Versand via mail fehlgeschlagen."
exit 1
fi
else
if ! echo -e "${body}" | mail -s "${subject}" "${NOTIFY_MAIL}"; then
log "ERROR" "E-Mail Versand via mail fehlgeschlagen."
exit 1
fi
fi
else
log "ERROR" "Weder sendmail noch mail verfügbar."
exit 1
fi
}
# --- 14 TAGE LOG ROTATION ---
current_time=$(date +%s)
if [ -f "${LOG_CYCLE_FILE}" ]; then
cycle_start=$(cat "${LOG_CYCLE_FILE}")
else
cycle_start=${current_time}
echo "${cycle_start}" > "${LOG_CYCLE_FILE}"
fi
# 14 Tage in Sekunden = 1209600
if [ $(( current_time - cycle_start )) -ge 1209600 ]; then
log "INFO" "14-Tage Log-Zyklus erreicht. Werte Log aus..."
if [ -f "${LOG_FILE}" ] && grep -q "\[ERROR\]" "${LOG_FILE}"; then
log "INFO" "Es wurden Fehler im Log gefunden. Sende Logdatei per E-Mail an ${NOTIFY_MAIL}."
log_content=$(cat "${LOG_FILE}")
subj="PBS Datastore '${DATASTORE}' - 14-Tage Fehler-Log [${PIVOT_HOST}]"
mail_body="Im Überwachungszeitraum der letzten 14 Tage sind bei der Ausführung des Skripts Fehler aufgetreten.\nHier ist das komplette Logfile der letzten 14 Tage:\n\n${log_content}"
send_mail "${subj}" "${mail_body}"
else
log "INFO" "Keine Fehler im Überwachungszeitraum aufgetreten."
fi
# Logfile leeren und neuen Zyklus starten
> "${LOG_FILE}"
echo "${current_time}" > "${LOG_CYCLE_FILE}"
log "INFO" "Logdatei zurückgesetzt. Neuer 14-Tage Zyklus gestartet."
fi
log "INFO" "--- Starte Überprüfung für Datastore '${DATASTORE}' ---"
# Voraussetzungen prüfen
command_exists() { command -v "$1" >/dev/null 2>&1; }
if ! command_exists proxmox-backup-debug; then
log "ERROR" "proxmox-backup-debug fehlt. Skript muss als root auf PBS laufen."
exit 1
fi
if ! command_exists jq || ! command_exists awk; then
log "ERROR" "jq oder awk fehlt. Bitte installieren."
exit 1
fi
# Einheit umwandeln: Basis 1000 (Exakt wie die PBS GUI rechnet!)
bytes_to_human() {
local b="$1"
awk -v b="$b" 'BEGIN {
if (b >= 1000000000000) printf "%.2f TB", b/1000000000000
else if (b >= 1000000000) printf "%.2f GB", b/1000000000
else if (b >= 1000000) printf "%.2f MB", b/1000000
else if (b <= -1000000000) printf "%.2f GB", b/1000000000
else printf "%d B", b
}'
}
# 1. Daten von der API abrufen
if ! json_out="$(proxmox-backup-debug api get /status/datastore-usage --output-format json 2>/dev/null)"; then
log "ERROR" "Abrufen der Datastore-Daten von der API fehlgeschlagen."
exit 1
fi
ds_json="$(printf '%s' "${json_out}" | jq -r --arg ds "${DATASTORE}" '.[] | select(.store == $ds)')"
if [ -z "${ds_json}" ]; then
log "ERROR" "Datastore '${DATASTORE}' nicht in der API gefunden."
exit 1
fi
# Rohe Byte-Werte aus der API lesen
used="$(printf '%s' "${ds_json}" | jq -r '.used // empty')"
avail="$(printf '%s' "${ds_json}" | jq -r '.avail // empty')"
if [ -z "${avail}" ] || [ -z "${used}" ]; then
log "ERROR" "API lieferte unvollständige Daten (used/avail)."
exit 1
fi
# WICHTIG: Die PBS GUI ignoriert den "total" Wert der API (da dieser die ext4-Root-Reserve enthält).
# Stattdessen berechnet die GUI die Gesamtgröße dynamisch aus den nutzbaren Werten:
total=$(( used + avail ))
# 2. Prozentwerte berechnen
avail_percent_int="$(( avail * 100 / total ))"
avail_percent_fmt="$(awk -v a="${avail}" -v t="${total}" 'BEGIN { printf "%.2f", a*100/t }')"
used_percent_fmt="$(awk -v u="${used}" -v t="${total}" 'BEGIN { printf "%.2f", u*100/t }')"
# 3. Trend-Analyse
growth_per_day_bytes=0
days_until_full="Unbekannt (zu wenig Daten)"
trend_string="Speicher wächst aktuell nicht."
if [ -f "${STATE_FILE}" ]; then
read -r last_time last_used < "${STATE_FILE}"
time_diff=$(( current_time - last_time ))
used_diff=$(( used - last_used ))
if [ "${time_diff}" -ge 3600 ]; then
growth_per_day_bytes=$(awk -v diff="${used_diff}" -v t="${time_diff}" 'BEGIN { printf "%d", (diff / t) * 86400 }')
if [ "${growth_per_day_bytes}" -gt 0 ]; then
days_left=$(awk -v a="${avail}" -v g="${growth_per_day_bytes}" 'BEGIN { printf "%d", a / g }')
days_until_full="${days_left} Tagen"
trend_string="$(bytes_to_human "${growth_per_day_bytes}") pro Tag"
elif [ "${growth_per_day_bytes}" -lt 0 ]; then
trend_string="Speicher wird freigegeben ($(bytes_to_human "${growth_per_day_bytes}") pro Tag)"
days_until_full="N/A (Speicher sinkt)"
fi
fi
fi
if [ ! -f "${STATE_FILE}" ] || [ "${time_diff:-0}" -ge 86400 ]; then
echo "${current_time} ${used}" > "${STATE_FILE}"
fi
# 4. Ausgabe formatieren
total_human="$(bytes_to_human "${total}")"
used_human="$(bytes_to_human "${used}")"
avail_human="$(bytes_to_human "${avail}")"
log "INFO" "Status: Gesamt ${total_human} | Belegt ${used_human} (${used_percent_fmt}%) | Frei ${avail_human} (${avail_percent_fmt}%)"
log "INFO" "Trend: Wachstum ${trend_string} | Voll in: ${days_until_full}"
body_text=$(printf \
'Server: %s
Datastore: %s
Speicherübersicht:
------------------
Gesamt: %s
Belegt: %s (%s%%)
Verfügbar: %s (%s%%)
Trend & Prognose:
-----------------
Wachstum: %s
Voraussichtlich voll in: %s
' \
"${PIVOT_HOST}" "${DATASTORE}" \
"${total_human}" \
"${used_human}" "${used_percent_fmt}" \
"${avail_human}" "${avail_percent_fmt}" \
"${trend_string}" "${days_until_full}")
# 5. Senden
if [ "${MODE}" = "report" ]; then
log "INFO" "Report-Modus aktiv. Sende Status-E-Mail."
subject="Status: PBS Datastore '${DATASTORE}' - ${avail_percent_fmt}% frei [${PIVOT_HOST}]"
send_mail "${subject}" "Täglicher Status-Bericht für Datastore Speicherplatz:\n\n${body_text}"
log "INFO" "Prüfung abgeschlossen."
exit 0
fi
if [ "${avail_percent_int}" -lt "${WARN_THRESHOLD_PERCENT}" ]; then
log "WARNING" "Schwellenwert unterschritten (${avail_percent_fmt}% < ${WARN_THRESHOLD_PERCENT}%). Sende Warn-E-Mail."
subject="WARNUNG: PBS Datastore '${DATASTORE}' - Nur noch ${avail_percent_fmt}% frei [${PIVOT_HOST}]"
warn_header="ACHTUNG: Der verfügbare Speicherplatz liegt unter dem konfigurierten Schwellenwert von ${WARN_THRESHOLD_PERCENT}%!\n\n"
send_mail "${subject}" "${warn_header}${body_text}"
else
log "INFO" "Speicherplatz ausreichend. Keine Aktion erforderlich."
fi
log "INFO" "Prüfung erfolgreich abgeschlossen."
exit 0
Ich bedanke mich schonmal im Vorraus für jede hilfe.
#LearningByDoing
PS: für Dieses Script wurde Kaum bis keine KI genutzt.
Bedeutet ich nutze VS-Code zum Programmieren welches die automatische einrückung für mich vornimmt, aber nicht beim Code Schreiben allgemein hilf..
Ich lerne durch meine Fehler und suche mir fast alles durch Tutorials zusammen.
MFG