diff --git a/pve_status_report.sh b/pve_status_report.sh new file mode 100644 index 0000000..2eec9a1 --- /dev/null +++ b/pve_status_report.sh @@ -0,0 +1,137 @@ +#!/bin/bash + +# CONFIGURATION +TELEGRAM_BOT_TOKEN="XXXXXXXXX:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" +TELEGRAM_CHAT_ID="-XXXXXXXXXX" +HOSTNAME="pve" +NOW=$(date "+%Y-%m-%d %H:%M") +CPU_CORES=$(nproc) +ONLINE="" +OFFLINE="" + +# Uptime hôte +UPTIME_SEC=$(cut -d. -f1 /proc/uptime) +UPTIME_H=$((UPTIME_SEC / 3600)) +UPTIME_M=$((UPTIME_SEC % 3600 / 60)) +if [ "$UPTIME_H" -ge 24 ]; then + D=$((UPTIME_H / 24)) + H=$((UPTIME_H % 24)) + UPTIME="${D}j$(printf "%02d" $H)h" +else + UPTIME="${UPTIME_H}h$(printf "%02d" $UPTIME_M)" +fi + +# Ressources hôte +CPU_USAGE=$(top -bn1 | grep "Cpu(s)" | awk '{print 100 - $8}' | cut -d. -f1) +LOAD_AVG=$(uptime | awk -F'load average:' '{ print $2 }' | sed 's/^ //') +MEM_TOTAL=$(free -m | awk '/Mem:/ { print $2 }') +MEM_USED=$(free -m | awk '/Mem:/ { print $3 }') +MEM_PERCENT=$(awk "BEGIN {printf \"%.1f\", $MEM_USED/$MEM_TOTAL*100}") +DISK_INFO=$(df -h / | awk 'NR==2') +DISK_USED=$(echo "$DISK_INFO" | awk '{print $3}') +DISK_TOTAL=$(echo "$DISK_INFO" | awk '{print $2}') +DISK_PERCENT=$(echo "$DISK_INFO" | awk '{gsub("%", "", $5); print $5}') + +# LXC Containers +for ID in $(pct list | awk 'NR>1 {print $1}'); do + CONF="/etc/pve/lxc/${ID}.conf" + NAME=$(awk -F': ' '/^hostname:/ {print $2}' "$CONF") + STATUS=$(pct status "$ID" | awk '{print $2}') + MEM_TOTAL_MB=$(pct config "$ID" | awk '/memory:/ {print $2}') + [[ -z "$MEM_TOTAL_MB" ]] && MEM_TOTAL_MB=0 + + if [ "$STATUS" = "running" ]; then + # CPU usage from cgroup v2 + STAT_FILE="/sys/fs/cgroup/lxc/${ID}/cpu.stat" + if [[ -f "$STAT_FILE" ]]; then + USAGE1=$(awk '/usage_usec/ {print $2}' "$STAT_FILE") + sleep 1 + USAGE2=$(awk '/usage_usec/ {print $2}' "$STAT_FILE") + DELTA=$((USAGE2 - USAGE1)) + CPU=$(awk -v d="$DELTA" -v c="$CPU_CORES" 'BEGIN {printf "%.1f", d / 10000 / c}') + else + CPU="0" + fi + + MEM_MB=$(pct exec "$ID" -- free -m | awk '/Mem:/ {print $3}' 2>/dev/null || echo "0") + CT_UPTIME=$(pct exec "$ID" -- awk '{print int($1)}' /proc/uptime 2>/dev/null || echo "0") + UH=$((CT_UPTIME / 3600)) + UM=$((CT_UPTIME % 3600 / 60)) + if [ "$UH" -ge 24 ]; then + D=$((UH / 24)) + H=$((UH % 24)) + UPTIME_FMT="${D}j$(printf "%02d" $H)h" + else + UPTIME_FMT="${UH}h$(printf "%02d" $UM)" + fi + + ONLINE+="🟢 ${NAME} ${ID} +CPU ${CPU}%, RAM ${MEM_MB}/${MEM_TOTAL_MB} Mo, Uptime: ${UPTIME_FMT}"$'\n' + else + OFFLINE+="🔴 ${NAME} ${ID} +CPU 0%, RAM 0/${MEM_TOTAL_MB} Mo, Uptime: 0h00"$'\n' + fi +done + +# QEMU VMs +for ID in $(qm list | awk 'NR>1 {print $1}'); do + CONF="/etc/pve/qemu-server/${ID}.conf" + NAME=$(awk -F': ' '/^name:/ {print $2}' "$CONF") + STATUS=$(qm status "$ID" | awk '{print $2}') + + if [ "$STATUS" = "running" ]; then + INFO=$(qm status "$ID" --verbose) + PID=$(echo "$INFO" | awk '/^pid:/ {print $2}') + CPU="0" + if [[ "$PID" =~ ^[0-9]+$ ]]; then + CPU_LINE=$(ps -p "$PID" -o %cpu= 2>/dev/null) + CPU=$(awk -v val="${CPU_LINE:-0}" 'BEGIN {printf "%.1f", val}') + fi + [[ "$CPU" == "0.0" ]] && CPU="0" + + MEM_USED=$(echo "$INFO" | awk '/^mem:/ {print int($2 / 1024 / 1024)}') + MEM_TOTAL=$(echo "$INFO" | awk '/^maxmem:/ {print int($2 / 1024 / 1024)}') + UPTIME_SEC=$(echo "$INFO" | awk '/^uptime:/ {print $2}') + UH=$((UPTIME_SEC / 3600)) + UM=$((UPTIME_SEC % 3600 / 60)) + if [ "$UH" -ge 24 ]; then + D=$((UH / 24)) + H=$((UH % 24)) + UPTIME_FMT="${D}j$(printf "%02d" $H)h" + else + UPTIME_FMT="${UH}h$(printf "%02d" $UM)" + fi + + ONLINE+="🟢 ${NAME} ${ID} +CPU ${CPU}%, RAM ${MEM_USED}/${MEM_TOTAL} Mo, Uptime: ${UPTIME_FMT}"$'\n' + else + MEM_TOTAL=$(qm config "$ID" | awk '/^memory:/ {print $2}') + [[ -z "$MEM_TOTAL" ]] && MEM_TOTAL=0 + OFFLINE+="🔴 ${NAME} ${ID} +CPU 0%, RAM 0/${MEM_TOTAL} Mo, Uptime: 0h00"$'\n' + fi +done + +# Format message Telegram +REPORT="📊 État de PVE [${HOSTNAME}] – ${NOW} + +🖥️ Hôte ${HOSTNAME} +CPU : ${CPU_USAGE} % +Charge moyenne : ${LOAD_AVG} +RAM : ${MEM_PERCENT} % (${MEM_USED} Mo / ${MEM_TOTAL} Mo) +Disque : ${DISK_PERCENT} % (${DISK_USED} / ${DISK_TOTAL}) +Uptime : ${UPTIME} + +📦 VM & CT : + +🟢 En ligne : +${ONLINE:-Aucun} + +🔴 Hors ligne : +${OFFLINE:-Aucun} +" + +# Envoi Telegram +curl -s -X POST "https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/sendMessage" \ + --data-urlencode "chat_id=${TELEGRAM_CHAT_ID}" \ + --data-urlencode "text=${REPORT}"