Ultima attività 1753322487

Скрипт за Proxmox мониторинг

proxmox_mon.sh Raw
1#!/bin/bash
2
3# Надграден скрипт за цялостен мониторинг на Proxmox
4# Включва допълнителни проверки и подобрени отчети
5# Автор: Федя Серафиев
6# Версия: 2.0
7# Дата на последна промяна: 2025-07-24
8
9# Конфигурация
10SCRIPT_DIR="/opt/proxmox-monitor"
11LOG_FILE="$SCRIPT_DIR/monitor.log"
12STATUS_FILE="$SCRIPT_DIR/last_status.json"
13CONFIG_FILE="$SCRIPT_DIR/config.conf"
14BACKUP_DIR="$SCRIPT_DIR/backups"
15MAX_LOG_FILES=30
16MAX_BACKUP_FILES=10
17
18# Стандартна конфигурация
19DEFAULT_TELEGRAM_BOT_TOKEN=""
20DEFAULT_TELEGRAM_CHAT_ID=""
21DEFAULT_CHECK_INTERVAL=60
22DEFAULT_CPU_THRESHOLD=80
23DEFAULT_MEMORY_THRESHOLD=85
24DEFAULT_DISK_THRESHOLD=90
25DEFAULT_LOAD_THRESHOLD=5.0
26DEFAULT_NETWORK_THRESHOLD=80
27DEFAULT_TEMP_THRESHOLD=70
28DEFAULT_BACKUP_ENABLED=true
29DEFAULT_BACKUP_INTERVAL=86400 # 1 ден в секунди
30
31# Цветове за изход
32RED='\033[0;31m'
33GREEN='\033[0;32m'
34YELLOW='\033[1;33m'
35BLUE='\033[0;34m'
36MAGENTA='\033[0;35m'
37CYAN='\033[0;36m'
38NC='\033[0m' # Без цвят
39
40# Инициализация на скрипта
41init_script() {
42 echo -e "${BLUE}Инициализиране на Proxmox Monitor...${NC}"
43
44 # Създаване на директории
45 mkdir -p "$SCRIPT_DIR" "$BACKUP_DIR"
46
47 # Проверка за root потребител
48 if [[ $EUID -ne 0 ]]; then
49 echo -e "${RED}Грешка: Скриптът трябва да се изпълнява с root права${NC}"
50 return 1
51 fi
52
53 # Създаване на конфигурационен файл, ако не съществува
54 if [[ ! -f "$CONFIG_FILE" ]]; then
55 echo -e "${YELLOW}Създаване на нов конфигурационен файл...${NC}"
56 cat > "$CONFIG_FILE" << EOF
57# Конфигурация на Proxmox Monitor
58TELEGRAM_BOT_TOKEN="$DEFAULT_TELEGRAM_BOT_TOKEN"
59TELEGRAM_CHAT_ID="$DEFAULT_TELEGRAM_CHAT_ID"
60CHECK_INTERVAL=$DEFAULT_CHECK_INTERVAL
61CPU_THRESHOLD=$DEFAULT_CPU_THRESHOLD
62MEMORY_THRESHOLD=$DEFAULT_MEMORY_THRESHOLD
63DISK_THRESHOLD=$DEFAULT_DISK_THRESHOLD
64LOAD_THRESHOLD=$DEFAULT_LOAD_THRESHOLD
65NETWORK_THRESHOLD=$DEFAULT_NETWORK_THRESHOLD
66TEMP_THRESHOLD=$DEFAULT_TEMP_THRESHOLD
67BACKUP_ENABLED=$DEFAULT_BACKUP_ENABLED
68BACKUP_INTERVAL=$DEFAULT_BACKUP_INTERVAL
69EOF
70 echo -e "${YELLOW}Създаден е конфигурационен файл в $CONFIG_FILE${NC}"
71 echo -e "${YELLOW}Моля, редактирайте конфигурационния файл с вашите данни${NC}"
72 return 1
73 fi
74
75 # Зареждане на конфигурацията
76 source "$CONFIG_FILE"
77
78 # Валидиране на конфигурацията
79 if [[ -z "$TELEGRAM_BOT_TOKEN" || -z "$TELEGRAM_CHAT_ID" ]]; then
80 echo -e "${RED}Грешка: Telegram данни не са конфигурирани${NC}"
81 return 1
82 fi
83
84 # Проверка за необходими пакети
85 local required_packages=("curl" "bc" "jq" "lm-sensors")
86 local missing_packages=()
87
88 for pkg in "${required_packages[@]}"; do
89 if ! dpkg -l | grep -q "^ii $pkg "; then
90 missing_packages+=("$pkg")
91 fi
92 done
93
94 if [[ ${#missing_packages[@]} -gt 0 ]]; then
95 echo -e "${YELLOW}Инсталиране на липсващи пакети: ${missing_packages[*]}${NC}"
96 apt-get update
97 apt-get install -y "${missing_packages[@]}"
98 fi
99
100 # Ротация на логове
101 manage_logs
102
103 return 0
104}
105
106# Управление на логове и архиви
107manage_logs() {
108 # Ротация на логове
109 if [[ -f "$LOG_FILE" ]]; then
110 local log_size=$(du -k "$LOG_FILE" | cut -f1)
111 if [[ $log_size -gt 1024 ]]; then # 1MB
112 echo -e "${YELLOW}Ротация на логове...${NC}"
113 gzip -c "$LOG_FILE" > "$LOG_FILE.$(date +%Y%m%d%H%M%S).gz"
114 > "$LOG_FILE"
115
116 # Изтриване на стари логове
117 local old_logs=$(ls -t "$LOG_FILE".*.gz 2>/dev/null | tail -n +$((MAX_LOG_FILES+1)))
118 for old_log in $old_logs; do
119 rm -f "$old_log"
120 done
121 fi
122 fi
123
124 # Ротация на архиви
125 if [[ "$BACKUP_ENABLED" == true ]]; then
126 local old_backups=$(ls -t "$BACKUP_DIR"/status_*.json.gz 2>/dev/null | tail -n +$((MAX_BACKUP_FILES+1)))
127 for old_backup in $old_backups; do
128 rm -f "$old_backup"
129 done
130 fi
131}
132
133# Функция за логване
134log_message() {
135 local level="$1"
136 local message="$2"
137 local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
138
139 echo "$timestamp [$level] $message" >> "$LOG_FILE"
140
141 # Допълнително извеждане за грешки и предупреждения
142 case "$level" in
143 "ERROR")
144 echo -e "${RED}$timestamp [$level] $message${NC}" >&2
145 ;;
146 "WARNING")
147 echo -e "${YELLOW}$timestamp [$level] $message${NC}" >&2
148 ;;
149 "INFO")
150 echo -e "${BLUE}$timestamp [$level] $message${NC}" >&1
151 ;;
152 *)
153 echo "$timestamp [$level] $message" >&1
154 ;;
155 esac
156}
157
158# Изпращане на Telegram известие
159send_telegram_notification() {
160 local message="$1"
161 local parse_mode="${2:-HTML}"
162
163 # Ограничаване на дължината на съобщението (Telegram има лимит ~4096 символа)
164 if [[ ${#message} -gt 4000 ]]; then
165 message="${message:0:4000}... [съкратено]"
166 fi
167
168 local response=$(curl -s -X POST "https://api.telegram.org/bot$TELEGRAM_BOT_TOKEN/sendMessage" \
169 -d "chat_id=$TELEGRAM_CHAT_ID" \
170 -d "text=$message" \
171 -d "parse_mode=$parse_mode" \
172 -d "disable_web_page_preview=true" 2>&1)
173
174 local result=$?
175 if [[ $result -eq 0 ]]; then
176 log_message "INFO" "Telegram известието е изпратено успешно"
177 else
178 log_message "ERROR" "Грешка при изпращане на Telegram известие: $response"
179 fi
180 return $result
181}
182
183# Вземане на системна информация
184get_system_info() {
185 local hostname=$(hostname -f)
186 local uptime=$(uptime -p | sed 's/up //')
187 local kernel=$(uname -r)
188 local pve_version=$(pveversion | grep -oP "pve-manager\/\K[0-9.]+")
189 local cpu_model=$(grep "model name" /proc/cpuinfo | head -1 | cut -d: -f2 | sed 's/^[ \t]*//')
190 local cpu_cores=$(grep -c "^processor" /proc/cpuinfo)
191
192 echo "hostname:$hostname"
193 echo "uptime:$uptime"
194 echo "kernel:$kernel"
195 echo "pve_version:$pve_version"
196 echo "cpu_model:$cpu_model"
197 echo "cpu_cores:$cpu_cores"
198}
199
200# Вземане на CPU използване
201get_cpu_usage() {
202 local cpu_usage=$(top -bn1 | grep "Cpu(s)" | sed "s/.*, *\([0-9.]*\)%* id.*/\1/" | awk '{print 100 - $1}')
203 echo "${cpu_usage%.*}"
204}
205
206# Вземане на памет
207get_memory_usage() {
208 local mem_info=$(free -m | grep "Mem:")
209 local total=$(echo $mem_info | awk '{print $2}')
210 local used=$(echo $mem_info | awk '{print $3}')
211 local buff_cache=$(echo $mem_info | awk '{print $6}')
212 local available=$(free -m | grep "Mem:" | awk '{print $7}')
213 local percentage=$(( (total - available) * 100 / total ))
214 echo "$percentage"
215}
216
217# Вземане на дисково използване
218get_disk_usage() {
219 local disk_usage=$(df -h / | tail -1 | awk '{print $5}' | sed 's/%//')
220 echo "$disk_usage"
221}
222
223# Вземане на средно натоварване
224get_load_average() {
225 local load=$(uptime | awk -F'load average:' '{print $2}' | awk '{print $1}' | sed 's/,//')
226 echo "$load"
227}
228
229# Вземане на мрежова активност
230get_network_usage() {
231 local interface=$(ip route | grep default | awk '{print $5}' | head -1)
232 if [[ -z "$interface" ]]; then
233 echo "0:0"
234 return
235 fi
236
237 local rx1=$(cat /sys/class/net/$interface/statistics/rx_bytes)
238 local tx1=$(cat /sys/class/net/$interface/statistics/tx_bytes)
239 sleep 1
240 local rx2=$(cat /sys/class/net/$interface/statistics/rx_bytes)
241 local tx2=$(cat /sys/class/net/$interface/statistics/tx_bytes)
242
243 local rx=$(( (rx2 - rx1) / 1024 ))
244 local tx=$(( (tx2 - tx1) / 1024 ))
245
246 echo "$rx:$tx"
247}
248
249# Вземане на температура
250get_temperature() {
251 local temp=$(sensors | grep -E "Package|Tdie" | awk '{print $4}' | sed 's/+//;s/°C//')
252 echo "${temp%.*}"
253}
254
255# Проверка на ZFS пулове
256check_zfs_pools() {
257 if ! command -v zpool &> /dev/null; then
258 echo "NOT_AVAILABLE"
259 return
260 fi
261
262 local pools=$(zpool list -H -o name,health 2>/dev/null)
263 if [[ -z "$pools" ]]; then
264 echo "NO_POOLS"
265 return
266 fi
267
268 local issues=()
269 while IFS= read -r line; do
270 local pool=$(echo "$line" | awk '{print $1}')
271 local health=$(echo "$line" | awk '{print $2}')
272
273 if [[ "$health" != "ONLINE" ]]; then
274 issues+=("$pool:$health")
275 fi
276 done <<< "$pools"
277
278 if [[ ${#issues[@]} -gt 0 ]]; then
279 echo "ISSUES:${issues[*]}"
280 else
281 echo "OK"
282 fi
283}
284
285# Проверка на Proxmox услуги
286check_proxmox_services() {
287 local services=("pveproxy" "pvedaemon" "pvestatd" "pve-cluster" "corosync" "pve-ha-crm" "pve-ha-lrm" "pve-firewall")
288 local failed_services=()
289
290 for service in "${services[@]}"; do
291 if ! systemctl is-active --quiet "$service"; then
292 failed_services+=("$service")
293 fi
294 done
295
296 if [[ ${#failed_services[@]} -gt 0 ]]; then
297 echo "FAILED:${failed_services[*]}"
298 else
299 echo "OK"
300 fi
301}
302
303# Вземане на статус на контейнери/ВМ
304get_container_status() {
305 local containers=()
306 local vms=()
307
308 # Вземане на LXC контейнери
309 while IFS= read -r line; do
310 if [[ -n "$line" ]]; then
311 local vmid=$(echo "$line" | awk '{print $1}')
312 local status=$(echo "$line" | awk '{print $2}')
313 local name=$(echo "$line" | awk '{print $3}')
314 local ip=$(pct config "$vmid" | grep "ip=" | cut -d'=' -f2 | cut -d'/' -f1 | head -1)
315 containers+=("$vmid:$status:$name:LXC:$ip")
316 fi
317 done < <(pct list | tail -n +2)
318
319 # Вземане на ВМ
320 while IFS= read -r line; do
321 if [[ -n "$line" ]]; then
322 local vmid=$(echo "$line" | awk '{print $1}')
323 local status=$(echo "$line" | awk '{print $3}')
324 local name=$(echo "$line" | awk '{print $2}')
325 local ip=$(qm guest exec "$vmid" -- ip route get 1 | awk '{print $7}' | head -1)
326 vms+=("$vmid:$status:$name:VM:$ip")
327 fi
328 done < <(qm list | tail -n +2)
329
330 # Комбиниране и връщане
331 for item in "${containers[@]}" "${vms[@]}"; do
332 echo "$item"
333 done
334}
335
336# Проверка на използване на хранилище
337check_storage_usage() {
338 local storage_issues=()
339
340 while IFS= read -r line; do
341 if [[ -n "$line" ]]; then
342 local storage=$(echo "$line" | awk '{print $1}')
343 local usage=$(echo "$line" | awk '{print $6}' | sed 's/%//')
344 local total=$(echo "$line" | awk '{print $2}')
345 local avail=$(echo "$line" | awk '{print $4}')
346
347 if [[ "$usage" -gt "$DISK_THRESHOLD" ]]; then
348 storage_issues+=("$storage:$usage% (Налично: $avail от $total)")
349 fi
350 fi
351 done < <(pvesm status | tail -n +2)
352
353 if [[ ${#storage_issues[@]} -gt 0 ]]; then
354 echo "HIGH_USAGE:${storage_issues[*]}"
355 else
356 echo "OK"
357 fi
358}
359
360# Проверка на състоянието на батерията (за UPS)
361check_ups_status() {
362 if ! command -v upsc &> /dev/null; then
363 echo "NOT_AVAILABLE"
364 return
365 fi
366
367 local ups_list=$(upsc -l 2>/dev/null)
368 if [[ -z "$ups_list" ]]; then
369 echo "NO_UPS"
370 return
371 fi
372
373 local ups_name=$(echo "$ups_list" | head -1)
374 local status=$(upsc "$ups_name" 2>/dev/null | grep -E "battery.charge:|ups.status:")
375
376 if [[ -z "$status" ]]; then
377 echo "ERROR"
378 return
379 fi
380
381 local battery_charge=$(echo "$status" | grep "battery.charge:" | cut -d' ' -f2)
382 local ups_status=$(echo "$status" | grep "ups.status:" | cut -d' ' -f2)
383
384 if [[ "$ups_status" != "OL" || "$battery_charge" -lt 90 ]]; then
385 echo "ISSUE:$ups_status:$battery_charge%"
386 else
387 echo "OK:$ups_status:$battery_charge%"
388 fi
389}
390
391# Проверка на състоянието на RAID
392check_raid_status() {
393 if [[ -f "/proc/mdstat" ]]; then
394 local mdstat=$(grep -A1 "md" /proc/mdstat | tail -1)
395 if [[ "$mdstat" == *"UU"* ]]; then
396 echo "OK"
397 else
398 echo "DEGRADED:$mdstat"
399 fi
400 elif command -v megacli &> /dev/null; then
401 local raid_status=$(megacli -LDInfo -Lall -aAll | grep "State" | awk '{print $3}')
402 if [[ "$raid_status" == "Optimal" ]]; then
403 echo "OK"
404 else
405 echo "DEGRADED:$raid_status"
406 fi
407 else
408 echo "NOT_AVAILABLE"
409 fi
410}
411
412# Генериране на отчет за статус
413generate_status_report() {
414 local report_type="$1" # ALERT, RECOVERY, SUMMARY, или DETAILED
415 local issues="$2"
416
417 local system_info=$(get_system_info)
418 local hostname=$(echo "$system_info" | grep "hostname:" | cut -d: -f2)
419 local uptime=$(echo "$system_info" | grep "uptime:" | cut -d: -f2-)
420 local pve_version=$(echo "$system_info" | grep "pve_version:" | cut -d: -f2-)
421 local cpu_model=$(echo "$system_info" | grep "cpu_model:" | cut -d: -f2-)
422 local cpu_cores=$(echo "$system_info" | grep "cpu_cores:" | cut -d: -f2-)
423
424 local cpu_usage=$(get_cpu_usage)
425 local memory_usage=$(get_memory_usage)
426 local disk_usage=$(get_disk_usage)
427 local load_avg=$(get_load_average)
428 local temperature=$(get_temperature)
429 local network_usage=$(get_network_usage)
430 local rx=$(echo "$network_usage" | cut -d: -f1)
431 local tx=$(echo "$network_usage" | cut -d: -f2)
432 local zfs_status=$(check_zfs_pools)
433 local raid_status=$(check_raid_status)
434 local ups_status=$(check_ups_status)
435
436 local current_time=$(date '+%Y-%m-%d %H:%M:%S')
437
438 case "$report_type" in
439 "ALERT")
440 local icon="🚨"
441 local status="АВАРИЯ"
442 ;;
443 "RECOVERY")
444 local icon="✅"
445 local status="ВЪЗСТАНОВЯВАНЕ"
446 ;;
447 "SUMMARY")
448 local icon="📊"
449 local status="ОБЗОР"
450 ;;
451 "DETAILED")
452 local icon="🔍"
453 local status="ПОДРОБЕН"
454 ;;
455 *)
456 local icon="ℹ️"
457 local status="ИНФО"
458 ;;
459 esac
460
461 local message="$icon <b>Proxmox Monitor - $status</b> $icon
462
463<b>🖥️ Системна информация:</b>
464• Хост: <code>$hostname</code>
465• Време: <code>$current_time</code>
466• Uptime: <code>$uptime</code>
467• Версия: <code>$pve_version</code>
468• CPU: <code>$cpu_model</code> ($cpu_cores ядра)
469
470<b>📊 Системни ресурси:</b>
471• CPU: <code>$cpu_usage%</code> (Температура: <code>$temperature°C</code>)
472• Памет: <code>$memory_usage%</code>
473• Диск: <code>$disk_usage%</code>
474• Натоварване: <code>$load_avg</code>
475• Мрежа: ⬇️ <code>$rx KB/s</code> ⬆️ <code>$tx KB/s</code>"
476
477 # Добавяне на RAID статус
478 case "$raid_status" in
479 "OK")
480 message="$message
481• RAID: <code>Нормално</code>"
482 ;;
483 "DEGRADED"*)
484 local degraded_info=$(echo "$raid_status" | cut -d: -f2-)
485 message="$message
486• RAID: <code>Деградиран ($degraded_info)</code>"
487 ;;
488 *)
489 message="$message"
490 ;;
491 esac
492
493 # Добавяне на ZFS статус
494 case "$zfs_status" in
495 "OK")
496 message="$message
497• ZFS: <code>Нормално</code>"
498 ;;
499 "ISSUES"*)
500 local zfs_issues=$(echo "$zfs_status" | cut -d: -f2- | tr '|' ', ')
501 message="$message
502• ZFS: <code>Проблеми ($zfs_issues)</code>"
503 ;;
504 *)
505 message="$message"
506 ;;
507 esac
508
509 # Добавяне на UPS статус
510 case "$ups_status" in
511 "OK"*)
512 local ups_info=$(echo "$ups_status" | cut -d: -f2-)
513 message="$message
514• UPS: <code>Нормално ($ups_info)</code>"
515 ;;
516 "ISSUE"*)
517 local ups_info=$(echo "$ups_status" | cut -d: -f2-)
518 message="$message
519• UPS: <code>Проблем ($ups_info)</code>"
520 ;;
521 *)
522 message="$message"
523 ;;
524 esac
525
526 # Добавяне на статус на контейнери
527 local container_status=$(get_container_status)
528 local running_count=0
529 local stopped_count=0
530 local problem_containers=()
531
532 while IFS= read -r line; do
533 if [[ -n "$line" ]]; then
534 local vmid=$(echo "$line" | cut -d: -f1)
535 local status=$(echo "$line" | cut -d: -f2)
536 local name=$(echo "$line" | cut -d: -f3)
537 local type=$(echo "$line" | cut -d: -f4)
538 local ip=$(echo "$line" | cut -d: -f5)
539
540 if [[ "$status" == "running" ]]; then
541 ((running_count++))
542 else
543 ((stopped_count++))
544 problem_containers+=("$type $vmid ($name) [$ip]: $status")
545 fi
546 fi
547 done <<< "$container_status"
548
549 message="$message
550
551<b>🔧 Контейнери/ВМ:</b>
552• Работят: <code>$running_count</code>
553• Спряни: <code>$stopped_count</code>"
554
555 # Добавяне на проблеми, ако има
556 if [[ -n "$issues" ]]; then
557 message="$message
558
559<b>⚠️ Открити проблеми:</b>
560$issues"
561 fi
562
563 # Добавяне на детайли за спрени контейнери
564 if [[ ${#problem_containers[@]} -gt 0 ]]; then
565 message="$message
566
567<b>🔴 Спрени контейнери/ВМ:</b>"
568 for container in "${problem_containers[@]}"; do
569 message="$message
570• <code>$container</code>"
571 done
572 fi
573
574 # Добавяне на подробна информация за хранилища
575 if [[ "$report_type" == "DETAILED" ]]; then
576 message="$message
577
578<b>💾 Хранилища:</b>"
579
580 while IFS= read -r line; do
581 if [[ -n "$line" ]]; then
582 local storage=$(echo "$line" | awk '{print $1}')
583 local type=$(echo "$line" | awk '{print $2}')
584 local status=$(echo "$line" | awk '{print $3}')
585 local total=$(echo "$line" | awk '{print $4}')
586 local used=$(echo "$line" | awk '{print $5}')
587 local avail=$(echo "$line" | awk '{print $6}')
588
589 message="$message
590• <code>$storage</code> ($type): $status | Използвано: $used от $total | Свободно: $avail"
591 fi
592 done < <(pvesm status | tail -n +2)
593 fi
594
595 echo "$message"
596}
597
598# Проверка на здравето на системата
599check_system_health() {
600 local issues=()
601 local current_status=()
602
603 # Проверка на CPU
604 local cpu_usage=$(get_cpu_usage)
605 if [[ "$cpu_usage" -gt "$CPU_THRESHOLD" ]]; then
606 issues+=("Високо CPU използване: ${cpu_usage}% (Лимит: ${CPU_THRESHOLD}%)")
607 fi
608 current_status+=("cpu:$cpu_usage")
609
610 # Проверка на памет
611 local memory_usage=$(get_memory_usage)
612 if [[ "$memory_usage" -gt "$MEMORY_THRESHOLD" ]]; then
613 issues+=("Високо използване на памет: ${memory_usage}% (Лимит: ${MEMORY_THRESHOLD}%)")
614 fi
615 current_status+=("memory:$memory_usage")
616
617 # Проверка на диск
618 local disk_usage=$(get_disk_usage)
619 if [[ "$disk_usage" -gt "$DISK_THRESHOLD" ]]; then
620 issues+=("Високо дисково използване: ${disk_usage}% (Лимит: ${DISK_THRESHOLD}%)")
621 fi
622 current_status+=("disk:$disk_usage")
623
624 # Проверка на натоварване
625 local load_avg=$(get_load_average)
626 if (( $(echo "$load_avg > $LOAD_THRESHOLD" | bc -l) )); then
627 issues+=("Високо средно натоварване: $load_avg (Лимит: $LOAD_THRESHOLD)")
628 fi
629 current_status+=("load:$load_avg")
630
631 # Проверка на температура
632 local temperature=$(get_temperature)
633 if [[ "$temperature" -gt "$TEMP_THRESHOLD" ]]; then
634 issues+=("Висока температура на CPU: ${temperature}°C (Лимит: ${TEMP_THRESHOLD}°C)")
635 fi
636 current_status+=("temp:$temperature")
637
638 # Проверка на мрежа
639 local network_usage=$(get_network_usage)
640 local rx=$(echo "$network_usage" | cut -d: -f1)
641 local tx=$(echo "$network_usage" | cut -d: -f2)
642 if [[ "$rx" -gt "$NETWORK_THRESHOLD" ]]; then
643 issues+=("Високо входящо мрежово натоварване: ${rx}KB/s (Лимит: ${NETWORK_THRESHOLD}KB/s)")
644 fi
645 if [[ "$tx" -gt "$NETWORK_THRESHOLD" ]]; then
646 issues+=("Високо изходящо мрежово натоварване: ${tx}KB/s (Лимит: ${NETWORK_THRESHOLD}KB/s)")
647 fi
648 current_status+=("network_rx:$rx")
649 current_status+=("network_tx:$tx")
650
651 # Проверка на Proxmox услуги
652 local service_status=$(check_proxmox_services)
653 if [[ "$service_status" != "OK" ]]; then
654 local failed_services=$(echo "$service_status" | cut -d: -f2 | tr '|' ', ')
655 issues+=("Неуспешни услуги: $failed_services")
656 fi
657 current_status+=("services:$service_status")
658
659 # Проверка на хранилище
660 local storage_status=$(check_storage_usage)
661 if [[ "$storage_status" != "OK" ]]; then
662 local storage_issues=$(echo "$storage_status" | cut -d: -f2 | tr '|' ', ')
663 issues+=("Проблеми с хранилище: $storage_issues")
664 fi
665 current_status+=("storage:$storage_status")
666
667 # Проверка на ZFS
668 local zfs_status=$(check_zfs_pools)
669 if [[ "$zfs_status" == "ISSUES"* ]]; then
670 local zfs_issues=$(echo "$zfs_status" | cut -d: -f2 | tr '|' ', ')
671 issues+=("Проблеми с ZFS: $zfs_issues")
672 fi
673 current_status+=("zfs:$zfs_status")
674
675 # Проверка на RAID
676 local raid_status=$(check_raid_status)
677 if [[ "$raid_status" == "DEGRADED"* ]]; then
678 local raid_issues=$(echo "$raid_status" | cut -d: -f2)
679 issues+=("Проблеми с RAID: $raid_issues")
680 fi
681 current_status+=("raid:$raid_status")
682
683 # Проверка на UPS
684 local ups_status=$(check_ups_status)
685 if [[ "$ups_status" == "ISSUE"* ]]; then
686 local ups_issues=$(echo "$ups_status" | cut -d: -f2-)
687 issues+=("Проблеми с UPS: $ups_issues")
688 fi
689 current_status+=("ups:$ups_status")
690
691 # Проверка на контейнери
692 local container_status=$(get_container_status)
693 local stopped_containers=()
694
695 while IFS= read -r line; do
696 if [[ -n "$line" ]]; then
697 local vmid=$(echo "$line" | cut -d: -f1)
698 local status=$(echo "$line" | cut -d: -f2)
699 local name=$(echo "$line" | cut -d: -f3)
700 local type=$(echo "$line" | cut -d: -f4)
701
702 if [[ "$status" != "running" ]]; then
703 stopped_containers+=("$type $vmid ($name)")
704 fi
705 fi
706 done <<< "$container_status"
707
708 if [[ ${#stopped_containers[@]} -gt 0 ]]; then
709 issues+=("Спряни контейнери: ${stopped_containers[*]}")
710 fi
711 current_status+=("containers:${#stopped_containers[@]}_stopped")
712
713 # Запазване на текущия статус
714 printf '%s\n' "${current_status[@]}" > "$STATUS_FILE"
715
716 # Архивиране на статуса
717 if [[ "$BACKUP_ENABLED" == true ]]; then
718 local last_backup=$(stat -c %Y "$STATUS_FILE" 2>/dev/null || echo 0)
719 local current_time=$(date +%s)
720
721 if (( current_time - last_backup > BACKUP_INTERVAL )); then
722 gzip -c "$STATUS_FILE" > "$BACKUP_DIR/status_$(date +%Y%m%d%H%M%S).json.gz"
723 fi
724 fi
725
726 # Връщане на проблеми
727 if [[ ${#issues[@]} -gt 0 ]]; then
728 printf '%s\n' "${issues[@]}"
729 fi
730}
731
732# Главна функция за мониторинг
733monitor_system() {
734 if ! init_script; then
735 exit 1
736 fi
737
738 local issues=$(check_system_health)
739 local previous_issues=""
740
741 # Зареждане на предишен статус
742 if [[ -f "$STATUS_FILE.prev" ]]; then
743 previous_issues=$(cat "$STATUS_FILE.prev" 2>/dev/null || echo "")
744 fi
745
746 # Текущи проблеми като стринг
747 local current_issues_str=""
748 if [[ -n "$issues" ]]; then
749 current_issues_str=$(echo "$issues" | tr '\n' '|')
750 fi
751
752 # Проверка дали статуса е променен
753 if [[ "$current_issues_str" != "$previous_issues" ]]; then
754 if [[ -n "$issues" ]]; then
755 # Открити са нови проблеми
756 local formatted_issues=""
757 while IFS= read -r issue; do
758 formatted_issues="$formatted_issues$issue\n"
759 done <<< "$issues"
760
761 local report=$(generate_status_report "ALERT" "$formatted_issues")
762 send_telegram_notification "$report"
763 log_message "ALERT" "Открити проблеми: $issues"
764 elif [[ -n "$previous_issues" ]]; then
765 # Проблемите са разрешени
766 local report=$(generate_status_report "RECOVERY" "")
767 send_telegram_notification "$report"
768 log_message "INFO" "Проблемите са разрешени"
769 fi
770
771 # Запазване на текущия статус като предишен
772 echo "$current_issues_str" > "$STATUS_FILE.prev"
773 fi
774}
775
776# Функция за инсталация
777install_monitor() {
778 echo -e "${BLUE}Инсталиране на Proxmox Monitor...${NC}"
779
780 # Проверка за root потребител
781 if [[ $EUID -ne 0 ]]; then
782 echo -e "${RED}Грешка: Скриптът трябва да се изпълнява с root права${NC}"
783 exit 1
784 fi
785
786 # Инсталиране на зависимости
787 log_message "INFO" "Инсталиране на зависимости..."
788 apt-get update
789 apt-get install -y curl bc jq lm-sensors megacli snmp nut
790
791 # Инициализиране на скрипта
792 if ! init_script; then
793 echo -e "${RED}Инсталацията неуспешна. Моля, конфигурирайте скрипта.${NC}"
794 exit 1
795 fi
796
797 # Създаване на systemd услуга
798 log_message "INFO" "Създаване на systemd услуга..."
799 cat > /etc/systemd/system/proxmox-monitor.service << EOF
800[Unit]
801Description=Proxmox Comprehensive Monitor
802After=network.target
803
804[Service]
805Type=simple
806User=root
807ExecStart=$0 daemon
808Restart=always
809RestartSec=10
810Environment="PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
811
812[Install]
813WantedBy=multi-user.target
814EOF
815
816 # Създаване на systemd таймер
817 log_message "INFO" "Създаване на systemd таймер..."
818 cat > /etc/systemd/system/proxmox-monitor.timer << EOF
819[Unit]
820Description=Proxmox Monitor Timer
821Requires=proxmox-monitor.service
822
823[Timer]
824OnBootSec=60
825OnUnitActiveSec=${CHECK_INTERVAL}s
826AccuracySec=1s
827
828[Install]
829WantedBy=timers.target
830EOF
831
832 # Активиране и стартиране на услугите
833 log_message "INFO" "Активиране на услугите..."
834 systemctl daemon-reload
835 systemctl enable proxmox-monitor.timer
836 systemctl start proxmox-monitor.timer
837
838 # Проверка на състоянието
839 sleep 2
840 local timer_status=$(systemctl is-active proxmox-monitor.timer)
841 local service_status=$(systemctl is-active proxmox-monitor.service)
842
843 if [[ "$timer_status" == "active" && "$service_status" == "active" ]]; then
844 echo -e "${GREEN}✅ Proxmox Monitor е инсталиран и стартиран успешно!${NC}"
845 echo -e "${YELLOW}Конфигурационен файл: $CONFIG_FILE${NC}"
846 echo -e "${YELLOW}Лог файл: $LOG_FILE${NC}"
847 echo -e "${YELLOW}Статус: systemctl status proxmox-monitor.timer${NC}"
848 log_message "INFO" "Успешна инсталация на Proxmox Monitor"
849 else
850 echo -e "${RED}❌ Грешка при инсталацията${NC}"
851 echo -e "${YELLOW}Състояние на таймера: $timer_status${NC}"
852 echo -e "${YELLOW}Състояние на услугата: $service_status${NC}"
853 log_message "ERROR" "Грешка при инсталация. Състояние на таймера: $timer_status, услугата: $service_status"
854 exit 1
855 fi
856}
857
858# Показване на употреба
859usage() {
860 echo "Употреба: $0 [команда]"
861 echo "Команди:"
862 echo " install - Инсталира и конфигурира монитора"
863 echo " daemon - Стартира като демон (използва се от systemd)"
864 echo " check - Извършва единична проверка"
865 echo " status - Показва текущия статус"
866 echo " summary - Изпраща обобщен отчет"
867 echo " detailed - Изпраща подробен отчет"
868 echo " test - Тества Telegram известието"
869 echo " config - Показва конфигурацията"
870 echo " logs - Показва последните логове"
871 echo " backup - Създава ръчно архивиране на статуса"
872 echo " help - Показва тази помощ"
873 exit 1
874}
875
876# Показване на текущия статус
877show_status() {
878 if ! init_script; then
879 exit 1
880 fi
881
882 echo -e "${BLUE}=== Статус на Proxmox Monitor ===${NC}"
883 echo
884
885 local system_info=$(get_system_info)
886 echo "$system_info" | while IFS=: read -r key value; do
887 echo -e "${GREEN}$key:${NC} $value"
888 done
889
890 echo
891 echo -e "${BLUE}=== Системни ресурси ===${NC}"
892 echo -e "${GREEN}CPU използване:${NC} $(get_cpu_usage)%"
893 echo -e "${GREEN}Използване на памет:${NC} $(get_memory_usage)%"
894 echo -e "${GREEN}Дисково използване:${NC} $(get_disk_usage)%"
895 echo -e "${GREEN}Средно натоварване:${NC} $(get_load_average)"
896 echo -e "${GREEN}Температура на CPU:${NC} $(get_temperature)°C"
897
898 local network_usage=$(get_network_usage)
899 echo -e "${GREEN}Мрежова активност:${NC} ⬇️ $(echo "$network_usage" | cut -d: -f1) KB/s ⬆️ $(echo "$network_usage" | cut -d: -f2) KB/s"
900
901 echo
902 echo -e "${BLUE}=== Услуги ===${NC}"
903 local service_status=$(check_proxmox_services)
904 if [[ "$service_status" == "OK" ]]; then
905 echo -e "${GREEN}Всички Proxmox услуги работят${NC}"
906 else
907 echo -e "${RED}Неуспешни услуги: $(echo "$service_status" | cut -d: -f2)${NC}"
908 fi
909
910 echo
911 echo -e "${BLUE}=== ZFS ===${NC}"
912 local zfs_status=$(check_zfs_pools)
913 case "$zfs_status" in
914 "OK")
915 echo -e "${GREEN}Всички ZFS пулове са нормални${NC}"
916 ;;
917 "ISSUES"*)
918 echo -e "${RED}Проблеми с ZFS: $(echo "$zfs_status" | cut -d: -f2)${NC}"
919 ;;
920 "NO_POOLS")
921 echo -e "${YELLOW}Няма ZFS пулове${NC}"
922 ;;
923 *)
924 echo -e "${YELLOW}ZFS статус: $zfs_status${NC}"
925 ;;
926 esac
927
928 echo
929 echo -e "${BLUE}=== RAID ===${NC}"
930 local raid_status=$(check_raid_status)
931 case "$raid_status" in
932 "OK")
933 echo -e "${GREEN}RAID масивът е нормален${NC}"
934 ;;
935 "DEGRADED"*)
936 echo -e "${RED}Проблеми с RAID: $(echo "$raid_status" | cut -d: -f2)${NC}"
937 ;;
938 *)
939 echo -e "${YELLOW}RAID статус: $raid_status${NC}"
940 ;;
941 esac
942
943 echo
944 echo -e "${BLUE}=== UPS ===${NC}"
945 local ups_status=$(check_ups_status)
946 case "$ups_status" in
947 "OK"*)
948 echo -e "${GREEN}UPS статус: $(echo "$ups_status" | cut -d: -f2-)${NC}"
949 ;;
950 "ISSUE"*)
951 echo -e "${RED}Проблеми с UPS: $(echo "$ups_status" | cut -d: -f2-)${NC}"
952 ;;
953 "NO_UPS")
954 echo -e "${YELLOW}Няма конфигуриран UPS${NC}"
955 ;;
956 *)
957 echo -e "${YELLOW}UPS статус: $ups_status${NC}"
958 ;;
959 esac
960
961 echo
962 echo -e "${BLUE}=== Контейнери/ВМ ===${NC}"
963 local container_status=$(get_container_status)
964 local running=0
965 local stopped=0
966
967 while IFS= read -r line; do
968 if [[ -n "$line" ]]; then
969 local vmid=$(echo "$line" | cut -d: -f1)
970 local status=$(echo "$line" | cut -d: -f2)
971 local name=$(echo "$line" | cut -d: -f3)
972 local type=$(echo "$line" | cut -d: -f4)
973 local ip=$(echo "$line" | cut -d: -f5)
974
975 if [[ "$status" == "running" ]]; then
976 ((running++))
977 echo -e "${GREEN}$type $vmid ($name) [$ip]: $status${NC}"
978 else
979 ((stopped++))
980 echo -e "${RED}$type $vmid ($name) [$ip]: $status${NC}"
981 fi
982 fi
983 done <<< "$container_status"
984
985 echo
986 echo -e "${BLUE}Обобщение: ${GREEN}$running работят${NC}, ${RED}$stopped спрени${NC}"
987}
988
989# Тестване на Telegram известие
990test_telegram() {
991 if ! init_script; then
992 exit 1
993 fi
994
995 echo -e "${BLUE}Тестване на Telegram известие...${NC}"
996
997 local test_message="🧪 <b>Proxmox Monitor Тест</b>
998
999Това е тестово съобщение от вашата Proxmox система за мониторинг.
1000
1001<b>Система:</b> $(hostname)
1002<b>Време:</b> $(date)
1003<b>Статус:</b> ✅ Тестът е успешен
1004
1005<b>📊 Системни ресурси:</b>
1006• CPU: <code>$(get_cpu_usage)%</code>
1007• Памет: <code>$(get_memory_usage)%</code>
1008• Диск: <code>$(get_disk_usage)%</code>
1009• Натоварване: <code>$(get_load_average)</code>"
1010
1011 if send_telegram_notification "$test_message"; then
1012 echo -e "${GREEN}✅ Тестовото известие е изпратено успешно!${NC}"
1013 log_message "INFO" "Успешен тест на Telegram известие"
1014 else
1015 echo -e "${RED}❌ Грешка при изпращане на тестово известие${NC}"
1016 echo -e "${YELLOW}Моля, проверете вашата Telegram конфигурация${NC}"
1017 log_message "ERROR" "Грешка при тест на Telegram известие"
1018 fi
1019}
1020
1021# Създаване на ръчно архивиране
1022create_backup() {
1023 if ! init_script; then
1024 exit 1
1025 fi
1026
1027 echo -e "${BLUE}Създаване на архивиране на статуса...${NC}"
1028
1029 if [[ ! -f "$STATUS_FILE" ]]; then
1030 echo -e "${YELLOW}Няма данни за статус за архивиране${NC}"
1031 return
1032 fi
1033
1034 local backup_file="$BACKUP_DIR/status_$(date +%Y%m%d%H%M%S).json.gz"
1035 gzip -c "$STATUS_FILE" > "$backup_file"
1036
1037 if [[ $? -eq 0 ]]; then
1038 echo -e "${GREEN}✅ Успешно архивиране: $backup_file${NC}"
1039 log_message "INFO" "Успешно ръчно архивиране: $backup_file"
1040 else
1041 echo -e "${RED}❌ Грешка при архивиране${NC}"
1042 log_message "ERROR" "Грешка при ръчно архивиране"
1043 fi
1044}
1045
1046# Главно изпълнение
1047case "${1:-}" in
1048 "install")
1049 install_monitor
1050 ;;
1051 "daemon")
1052 while true; do
1053 monitor_system
1054 sleep "$CHECK_INTERVAL"
1055 done
1056 ;;
1057 "check")
1058 monitor_system
1059 ;;
1060 "status")
1061 show_status
1062 ;;
1063 "summary")
1064 if init_script; then
1065 report=$(generate_status_report "SUMMARY" "")
1066 send_telegram_notification "$report"
1067 echo -e "${GREEN}Обобщен отчет изпратен${NC}"
1068 fi
1069 ;;
1070 "detailed")
1071 if init_script; then
1072 report=$(generate_status_report "DETAILED" "")
1073 send_telegram_notification "$report"
1074 echo -e "${GREEN}Подробен отчет изпратен${NC}"
1075 fi
1076 ;;
1077 "test")
1078 test_telegram
1079 ;;
1080 "config")
1081 if [[ -f "$CONFIG_FILE" ]]; then
1082 echo -e "${BLUE}=== Конфигурация ===${NC}"
1083 cat "$CONFIG_FILE"
1084 else
1085 echo -e "${RED}Конфигурационен файл не е намерен${NC}"
1086 fi
1087 ;;
1088 "logs")
1089 if [[ -f "$LOG_FILE" ]]; then
1090 echo -e "${BLUE}=== Последни 20 лога ===${NC}"
1091 tail -20 "$LOG_FILE"
1092 echo -e "\n${BLUE}=== Обобщение на грешките ===${NC}"
1093 grep -i "error" "$LOG_FILE" | tail -10
1094 else
1095 echo -e "${YELLOW}Няма намерени логове${NC}"
1096 fi
1097 ;;
1098 "backup")
1099 create_backup
1100 ;;
1101 "help"|*)
1102 usage
1103 ;;
1104esac