Python批量巡检系统资源(磁盘、内存、cpu、时间)将结果保存到csv文件

模块下载

指定清华源将包下载到本地,pip3 install在安装

pip3 download -r requirements.txt -d /root/python_rpms/  -i https://pypi.tuna.tsinghua.edu.cn/simple

文件里写需要的包名,也可以指定具体的模块版本

paramiko

requests

日志格式化脚本

format_logging.py 

import logging
import sys

# ANSI 颜色(终端生效)
class Colors:
    INFO = '\033[92m'      # 绿
    WARNING = '\033[93m'    # 黄
    ERROR = '\033[91m'      # 红
    CRITICAL = '\033[91m'   # 红
    RESET = '\033[0m'       # 重置

# 自定义 Formatter,在日志渲染时再决定颜色
class ColoredFormatter(logging.Formatter):
    def format(self, record):
        # record.levelname 这时已经是 "INFO" / "ERROR" 等真实值
        color = getattr(Colors, record.levelname, Colors.RESET)
        msg = super().format(record)
        return f"{color}{msg}{Colors.RESET}"

def setup_logger(
    name,
    logfile="system_check.log",
    level=logging.INFO,
    silent=False
):
    logger = logging.getLogger(name)
    if logger.handlers:          # 防止重复添加 handler
        return logger
    logger.setLevel(level)

    # 文件用普通格式(不带颜色,避免文件里出现乱码)
    file_fmt = logging.Formatter(
        fmt='%(asctime)s [%(levelname)s] %(message)s',
        datefmt='%Y-%m-%d %H:%M:%S'
    )
    fh = logging.FileHandler(logfile, encoding="utf-8")
    fh.setFormatter(file_fmt)
    logger.addHandler(fh)

    # 控制台用带颜色的 Formatter
    if not silent:
        console_fmt = ColoredFormatter(
            fmt='%(asctime)s [%(levelname)s] %(message)s',
            datefmt='%Y-%m-%d %H:%M:%S'
        )
        ch = logging.StreamHandler(sys.stdout)
        ch.setFormatter(console_fmt)
        logger.addHandler(ch)

    logger.propagate = False    # 禁止向上冒泡
    return logger

服务器信息文件csv

server.csv

巡检脚本

check_system.py

#!/usr/bin/python3
# -*- coding: utf-8 -*-
import csv
import paramiko
from datetime import datetime
from format_logging import setup_logger

# 日志调用
logger = setup_logger(__name__, silent=False)

# 巡检信息写到的文件
CSV_FILE = "server_check_result"
RUN_ID = datetime.now().strftime('%Y%m%d')
FINAL_FILE = f"{CSV_FILE}_{RUN_ID}.csv"

# 打开服务器文件,生成列表
def load_server_list(csv_file='server.csv'):
    with open(csv_file, mode='r', encoding='gbk') as f:
        reader = csv.DictReader(f)
        servers = list(reader)
    logger.info(f"成功读取 {len(servers)} 台服务器信息")
    return servers


# 通用的执行shell命令函数
def run_command(ssh, command):
    stdin, stdout, stderr = ssh.exec_command(command)
    result = stdout.read().decode().strip()
    return result


# 检测磁盘,获取使用率和剩余
def check_disk(ssh, ip):
    cmd_disk_used = "df -hT | awk '$NF==\"/\" {print $6}'"
    cmd_disk_avail = "df -hT | awk '$NF==\"/\" {print $5}'"

    disk_used = run_command(ssh, cmd_disk_used)
    disk_avail = run_command(ssh, cmd_disk_avail)

    if disk_used and disk_avail:
        logger.info(f"[{ip}] 根盘使用率:已用{disk_used}%, 可用{disk_avail}")
    else:
        logger.warning(f"未获取到 [{ip}] 的磁盘信息]")
        disk_used = disk_used or "N/A"
        disk_avail = disk_avail or "N/A"

    return disk_used, disk_avail


# 检测内存,获取使用率和剩余
def check_memory(ssh, ip):
    cmd_free_used = "free -h | awk '/Mem/ {print $4}'"
    cmd_free_avail = "free -h | awk '/Mem/ {print $7}'"

    free_mem = run_command(ssh, cmd_free_used)
    avail_mem = run_command(ssh, cmd_free_avail)

    if free_mem and avail_mem:
        logger.info(f"[{ip}] 内存使用情况:free={free_mem}, available={avail_mem}")
    else:
        logger.warning(f"未获取到 [{ip}] 的内存信息")
        free_mem = free_mem or "N/A"
        avail_mem = avail_mem or "N/A"

    return free_mem, avail_mem


def check_system_time(ssh, ip):
    cmd_time = "date"
    system_time = run_command(ssh, cmd_time)
    if system_time:
        logger.info(f"[{ip}] 当前系统时间:{system_time}")
    else:
        logger.warning(f"未获取到 [{ip}] 的系统时间 ")
    return system_time


def check_cpu(ssh, ip):
    cmd_cpu_id = "top -bn1 | grep 'Cpu(s)' | awk -F',' '{print 100 - $4}' | awk '{print $1}'"
    cpu_id = run_command(ssh, cmd_cpu_id)
    if cpu_id:
      logger.info(f"[{ip}] CPU使用率 {cpu_id}")
    else:
      logger.warning(f"未获取到 [{ip}] 的CPU信息")
    return cpu_id


# ssh连接执行命令
def connect_and_check(server):
    asset_name = server['资产名称']
    zone = server['区域']
    ip = server['IP']
    port = int(server['端口'])
    user = server['用户名']
    password = server['密码']

    logger.info(f"正在连接 {asset_name}-{zone}-{ip}:{port}")

    ssh = paramiko.SSHClient()
    ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())

    try:
        ssh.connect(
            hostname=ip,
            port=port,
            username=user,
            password=password,
            timeout=10
        )
        logger.info(f"连接成功 {ip}")

        # 执行检查命令
        disk_used, disk_avail = check_disk(ssh, ip)
        free_mem, avail_mem = check_memory(ssh, ip)
        system_time = check_system_time(ssh, ip)
        cpu_id = check_cpu(ssh, ip)
        # 保存结果到csv
        save_csv(
            server=server,
            disk_used=disk_used,
            disk_avail=disk_avail,
            free_mem=free_mem,
            avail_mem=avail_mem,
            cpu_id=cpu_id,
            system_time=system_time
        )

    except Exception as e:
        logger.error(f"连接 {ip} 失败: {e}")
    finally:
        ssh.close()
        logger.info(f"已关闭与 {ip} 的连接")
        print("-" * 60)


# 保存结果到csv
def save_csv(server, disk_used, disk_avail, free_mem, avail_mem, cpu_id, system_time):
    filename = FINAL_FILE

    # 判断文件是否存在
    import os
    file_exists = os.path.isfile(filename)

    with open(filename, mode='a', newline='', encoding='utf-8-sig') as f:
        writer = csv.writer(f)
        # 第一次写入时,先写表头
        if not file_exists:
            writer.writerow([
                '资产名称', '区域', 'IP', 'port', 'user',
                '磁盘使用率', '磁盘可用值',
                '内存使用', '内存可用值',
                'CPU使用率', '系统时间'
            ])

        # 写入数据行,从server字典读取
        writer.writerow([
            server.get('资产名称', ''),
            server.get('区域', ''),
            server.get('IP', ''),
            server.get('端口', ''),
            server.get('用户名', ''),
            disk_used,
            disk_avail,
            free_mem,
            avail_mem,
            cpu_id,
            system_time
        ])

    logger.info(f"[{server.get('IP')}] 结果已写入 {filename}")


# 主程序
if __name__ == '__main__':
    servers = load_server_list()

    for server in servers:
        connect_and_check(server)

    logger.info(f"全部检查完成,结果已保存至 {FINAL_FILE}")

终端执行

python3 check_system.py

查看csv文件和日志记录

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值