tg_monitor_bot/backup/monitor.py.bak

184 lines
7.5 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import paramiko
import time
import re
from collections import defaultdict
# Глобальный словарь для хранения предыдущих значений RX/TX (для расчета за час)
# Ключ: (host_ip, interface) -> {'rx': int, 'tx': int, 'time': timestamp}
prev_net_stats = {}
def get_ssh_client(host_config):
"""Создает SSH подключение"""
client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
try:
client.connect(
hostname=host_config['ip'],
port=host_config['port'],
username=host_config['user'],
key_filename=host_config['key_path'],
timeout=10
)
return client
except Exception as e:
return f"SSH Error: {str(e)}"
def exec_cmd(client, command):
"""Выполняет команду и возвращает вывод"""
try:
stdin, stdout, stderr = client.exec_command(command, timeout=10)
return stdout.read().decode('utf-8').strip()
except Exception as e:
return f"CMD Error: {str(e)}"
def collect_metrics(host_config):
"""Сбор всех метрик с одного хоста"""
client = get_ssh_client(host_config)
if isinstance(client, str):
return {"error": client}
result = {
"host": host_config['name'],
"ip": host_config['ip'],
"metrics": {}
}
# 1. CPU загрузка (%)
cpu_output = exec_cmd(client, "top -bn1 | grep 'Cpu(s)' | awk '{print $2}' | cut -d'%' -f1")
try:
result["metrics"]["cpu"] = float(cpu_output.replace(',', '.'))
except:
result["metrics"]["cpu"] = 0.0
# 2. ОЗУ (используется в MB и %)
mem_output = exec_cmd(client, "free -m | grep Mem")
parts = re.split(r'\s+', mem_output)
if len(parts) >= 3:
total_mem = int(parts[1])
used_mem = int(parts[2])
result["metrics"]["mem_used_mb"] = used_mem
result["metrics"]["mem_percent"] = round((used_mem / total_mem) * 100, 1)
else:
result["metrics"]["mem_used_mb"] = 0
result["metrics"]["mem_percent"] = 0
# 3. Uptime и Load Average
uptime_output = exec_cmd(client, "uptime")
# Парсим load average (1,5,15 мин)
load_avg = re.search(r'load average:\s+([\d.]+),\s+([\d.]+),\s+([\d.]+)', uptime_output)
if load_avg:
result["metrics"]["load_1"] = load_avg.group(1)
result["metrics"]["load_5"] = load_avg.group(2)
result["metrics"]["load_15"] = load_avg.group(3)
# Парсим uptime (дни/часы)
uptime_seconds = exec_cmd(client, "cat /proc/uptime | awk '{print $1}'")
try:
uptime_seconds = float(uptime_seconds.split('.')[0])
days = uptime_seconds // 86400
hours = (uptime_seconds % 86400) // 3600
minutes = (uptime_seconds % 3600) // 60
result["metrics"]["uptime"] = f"{int(days)}d {int(hours)}h {int(minutes)}m"
except:
result["metrics"]["uptime"] = "N/A"
# 4. Сеть (трафик за последний час)
# Сначала собираем текущие счетчики по всем интерфейсам (кроме lo)
net_output = exec_cmd(client, "cat /proc/net/dev | tail -n +3 | grep -v lo")
current_net = {}
for line in net_output.split('\n'):
if not line.strip():
continue
parts = re.split(r'\s+', line.strip())
iface = parts[0].replace(':', '')
rx_bytes = int(parts[1])
tx_bytes = int(parts[9])
current_net[iface] = {'rx': rx_bytes, 'tx': tx_bytes}
# Расчет за час (используем глобальный кеш)
global prev_net_stats
host_key = host_config['ip']
total_rx_hour = 0
total_tx_hour = 0
if host_key in prev_net_stats:
old_data = prev_net_stats[host_key]
for iface, vals in current_net.items():
if iface in old_data:
# Считаем разницу. Если перезагрузили сервер - счетчики сбросятся, это ок.
delta_rx = vals['rx'] - old_data[iface]['rx']
delta_tx = vals['tx'] - old_data[iface]['tx']
if delta_rx > 0:
total_rx_hour += delta_rx
if delta_tx > 0:
total_tx_hour += delta_tx
# Переводим в Мегабайты (для удобства)
result["metrics"]["net_rx_mb"] = round(total_rx_hour / (1024 * 1024), 2)
result["metrics"]["net_tx_mb"] = round(total_tx_hour / (1024 * 1024), 2)
# Сохраняем текущие значения для следующего замера
prev_net_stats[host_key] = current_net
# 5. Диски (iostat %util)
iostat_output = exec_cmd(client, "iostat -x -k 1 2 | grep -E 'sd[a-z]|vd[a-z]|nvme' | tail -n +3")
disk_stats = []
# Собираем все диски, показываем топ по нагрузке
for line in iostat_output.split('\n'):
if not line.strip():
continue
parts = re.split(r'\s+', line.strip())
if len(parts) >= 14:
disk_name = parts[0]
try:
util = float(parts[-1].replace(',', '.'))
rps = float(parts[3].replace(',', '.')) # read/s
wps = float(parts[4].replace(',', '.')) # write/s
disk_stats.append({
"name": disk_name,
"util": util,
"rps": rps,
"wps": wps
})
except:
pass
# Сортируем по утилизации и берем топ-3 самых нагруженных
disk_stats.sort(key=lambda x: x['util'], reverse=True)
result["metrics"]["disks"] = disk_stats[:3]
# 6. Температуры (если есть sensors)
temp_output = exec_cmd(client, "sensors -u 2>/dev/null | grep -E 'temp[0-9]+_input|Core' | head -5")
temps = []
if temp_output and "Error" not in temp_output:
# Парсим цифры
for line in temp_output.split('\n'):
if '_input:' in line:
val = re.search(r'([\d.]+)', line)
if val:
temps.append(float(val.group(1)))
result["metrics"]["temps"] = temps
# 7. Топ-5 процессов по CPU и RAM
top_cpu = exec_cmd(client, "ps aux --sort=-%cpu | head -6 | tail -5")
top_mem = exec_cmd(client, "ps aux --sort=-%mem | head -6 | tail -5")
result["metrics"]["top_cpu"] = top_cpu
result["metrics"]["top_mem"] = top_mem
# 8. Логи (ошибки, fail2ban)
# Проверяем системный журнал на панику/ошибки за последнюю минуту (чтобы не спамить)
last_logs = exec_cmd(client, "journalctl -p 3 -xn 5 --no-pager 2>/dev/null || dmesg | tail -5")
# Fail2ban статус
fail2ban_status = exec_cmd(client, "fail2ban-client status 2>/dev/null | grep 'Number of failed'")
if not fail2ban_status:
fail2ban_status = "Fail2ban not installed or inactive"
# Кто пытался прорваться (последние записи из логов)
fail2ban_logs = exec_cmd(client, "tail -10 /var/log/fail2ban.log 2>/dev/null | grep -i banned || echo 'No recent bans'")
result["metrics"]["logs_errors"] = last_logs
result["metrics"]["fail2ban_status"] = fail2ban_status
result["metrics"]["fail2ban_logs"] = fail2ban_logs
client.close()
return result