Son aktivite 1753322487

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

urocibg bu gisti düzenledi 1753322487. Düzenlemeye git

1 file changed, 1 insertion, 1 deletion

proxmox_mon.sh

@@ -4,7 +4,7 @@
4 4 # Включва допълнителни проверки и подобрени отчети
5 5 # Автор: Федя Серафиев
6 6 # Версия: 2.0
7 - # Дата на последна промяна: 2023-11-15
7 + # Дата на последна промяна: 2025-07-24
8 8
9 9 # Конфигурация
10 10 SCRIPT_DIR="/opt/proxmox-monitor"

urocibg bu gisti düzenledi 1753322444. Düzenlemeye git

1 file changed, 1104 insertions

proxmox_mon.sh(dosya oluşturuldu)

@@ -0,0 +1,1104 @@
1 + #!/bin/bash
2 +
3 + # Надграден скрипт за цялостен мониторинг на Proxmox
4 + # Включва допълнителни проверки и подобрени отчети
5 + # Автор: Федя Серафиев
6 + # Версия: 2.0
7 + # Дата на последна промяна: 2023-11-15
8 +
9 + # Конфигурация
10 + SCRIPT_DIR="/opt/proxmox-monitor"
11 + LOG_FILE="$SCRIPT_DIR/monitor.log"
12 + STATUS_FILE="$SCRIPT_DIR/last_status.json"
13 + CONFIG_FILE="$SCRIPT_DIR/config.conf"
14 + BACKUP_DIR="$SCRIPT_DIR/backups"
15 + MAX_LOG_FILES=30
16 + MAX_BACKUP_FILES=10
17 +
18 + # Стандартна конфигурация
19 + DEFAULT_TELEGRAM_BOT_TOKEN=""
20 + DEFAULT_TELEGRAM_CHAT_ID=""
21 + DEFAULT_CHECK_INTERVAL=60
22 + DEFAULT_CPU_THRESHOLD=80
23 + DEFAULT_MEMORY_THRESHOLD=85
24 + DEFAULT_DISK_THRESHOLD=90
25 + DEFAULT_LOAD_THRESHOLD=5.0
26 + DEFAULT_NETWORK_THRESHOLD=80
27 + DEFAULT_TEMP_THRESHOLD=70
28 + DEFAULT_BACKUP_ENABLED=true
29 + DEFAULT_BACKUP_INTERVAL=86400 # 1 ден в секунди
30 +
31 + # Цветове за изход
32 + RED='\033[0;31m'
33 + GREEN='\033[0;32m'
34 + YELLOW='\033[1;33m'
35 + BLUE='\033[0;34m'
36 + MAGENTA='\033[0;35m'
37 + CYAN='\033[0;36m'
38 + NC='\033[0m' # Без цвят
39 +
40 + # Инициализация на скрипта
41 + init_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
58 + TELEGRAM_BOT_TOKEN="$DEFAULT_TELEGRAM_BOT_TOKEN"
59 + TELEGRAM_CHAT_ID="$DEFAULT_TELEGRAM_CHAT_ID"
60 + CHECK_INTERVAL=$DEFAULT_CHECK_INTERVAL
61 + CPU_THRESHOLD=$DEFAULT_CPU_THRESHOLD
62 + MEMORY_THRESHOLD=$DEFAULT_MEMORY_THRESHOLD
63 + DISK_THRESHOLD=$DEFAULT_DISK_THRESHOLD
64 + LOAD_THRESHOLD=$DEFAULT_LOAD_THRESHOLD
65 + NETWORK_THRESHOLD=$DEFAULT_NETWORK_THRESHOLD
66 + TEMP_THRESHOLD=$DEFAULT_TEMP_THRESHOLD
67 + BACKUP_ENABLED=$DEFAULT_BACKUP_ENABLED
68 + BACKUP_INTERVAL=$DEFAULT_BACKUP_INTERVAL
69 + EOF
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 + # Управление на логове и архиви
107 + manage_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 + # Функция за логване
134 + log_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 известие
159 + send_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 + # Вземане на системна информация
184 + get_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 използване
201 + get_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 + # Вземане на памет
207 + get_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 + # Вземане на дисково използване
218 + get_disk_usage() {
219 + local disk_usage=$(df -h / | tail -1 | awk '{print $5}' | sed 's/%//')
220 + echo "$disk_usage"
221 + }
222 +
223 + # Вземане на средно натоварване
224 + get_load_average() {
225 + local load=$(uptime | awk -F'load average:' '{print $2}' | awk '{print $1}' | sed 's/,//')
226 + echo "$load"
227 + }
228 +
229 + # Вземане на мрежова активност
230 + get_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 + # Вземане на температура
250 + get_temperature() {
251 + local temp=$(sensors | grep -E "Package|Tdie" | awk '{print $4}' | sed 's/+//;s/°C//')
252 + echo "${temp%.*}"
253 + }
254 +
255 + # Проверка на ZFS пулове
256 + check_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 услуги
286 + check_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 + # Вземане на статус на контейнери/ВМ
304 + get_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 + # Проверка на използване на хранилище
337 + check_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)
361 + check_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
392 + check_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 + # Генериране на отчет за статус
413 + generate_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 + # Проверка на здравето на системата
599 + check_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 + # Главна функция за мониторинг
733 + monitor_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 + # Функция за инсталация
777 + install_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]
801 + Description=Proxmox Comprehensive Monitor
802 + After=network.target
803 +
804 + [Service]
805 + Type=simple
806 + User=root
807 + ExecStart=$0 daemon
808 + Restart=always
809 + RestartSec=10
810 + Environment="PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
811 +
812 + [Install]
813 + WantedBy=multi-user.target
814 + EOF
815 +
816 + # Създаване на systemd таймер
817 + log_message "INFO" "Създаване на systemd таймер..."
818 + cat > /etc/systemd/system/proxmox-monitor.timer << EOF
819 + [Unit]
820 + Description=Proxmox Monitor Timer
821 + Requires=proxmox-monitor.service
822 +
823 + [Timer]
824 + OnBootSec=60
825 + OnUnitActiveSec=${CHECK_INTERVAL}s
826 + AccuracySec=1s
827 +
828 + [Install]
829 + WantedBy=timers.target
830 + EOF
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 + # Показване на употреба
859 + usage() {
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 + # Показване на текущия статус
877 + show_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 известие
990 + test_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 + # Създаване на ръчно архивиране
1022 + create_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 + # Главно изпълнение
1047 + case "${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 + ;;
1104 + esac
Daha yeni Daha eski