Linux-Python operation and maintenance automatic inspection script

Operation and maintenance automatic inspection script instructions

createTime: 2022-12-21
createBy: lln
createInfo: 
检查服务器磁盘、内存、网络、docker容器等信息,以json格式输出至同目录下的report文件夹中,便于运维人员查看。

1. Environmental Description

Centos版本 >=7
Python2版本 >=2.6 (兼容python3)

2. Instructions for use

1、将脚本文件linuxOpsStartUp.py放入任意目录下
2、执行 python linuxOpsStartUp.py 命令,进行服务器信息检查,检查结果输出至同目录下report文件夹中。

3. Examples of inspection results

[
	{
		"最后启动": [
			"15:08 "
		],
		"发行版本": [
			"CentOS Linux release 7.9.2009 (Core)"
		],
		"当前时间": [
			"2022-12-20 17:50:13"
		],
		"系统": [
			"GNU/Linux"
		],
		"时区信息": [
			"Tue, 20 Dec 2022 17:50:13 +0800"
		],
		"运行时间": [
			"2022-12-20 17:50:13"
		],
		"内核": [
			"3.10.0-1160.6.1.el7.x86_64"
		],
		"主机名": [
			"localhost.localdomain"
		]
	},
	{
		"物理CPU个数": [
			"1"
		],
		"CPU架构": [
			"x86_64"
		],
		"每CPU核心数": [
			"4"
		],
		"CPU型号": [
			"Intel(R) Core(TM) i5-6400 CPU @ 2.70GHz"
		],
		"逻辑CPU个数": [
			"4"
		]
	},
	{
		"内存总览": [
			"              total        used        free      shared  buff/cache   available",
			"Mem:            15G        9.2G        307M        783M        5.9G        5.1G",
			"Swap:          7.8G        237M        7.6G"
		]
	},
	{
		"索引总量(MB)": 1125058,
		"硬盘使用量(GB)": 1060,
		"磁盘总览": [
			"文件系统                 容量  已用  可用 已用% 挂载点",
			"devtmpfs                 7.8G     0  7.8G    0% /dev",
			"tmpfs                    7.8G     0  7.8G    0% /dev/shm",
			"tmpfs                    7.8G  732M  7.1G   10% /run",
			"tmpfs                    7.8G     0  7.8G    0% /sys/fs/cgroup",
			"/dev/mapper/centos-root   50G   31G   20G   62% /",
			"/dev/sda2               1014M  188M  827M   19% /boot",
			"/dev/sda1                200M   12M  189M    6% /boot/efi",
			"/dev/mapper/centos-home  2.0T   38G  2.0T    2% /home",
			"tmpfs                    1.6G     0  1.6G    0% /run/user/0"
		],
		"硬盘总量(GB)": 3726,
		"硬盘使用比例(%)": "28.46%",
		"索引剩余量(MB)": 1095859,
		"索引使用量(MB)": 29198,
		"硬盘空余量(GB)": 2665,
		"索引使用比例(%)": "2.60%"
	},
	{
		"IP": [
			"enp3s0 192.168.11.127/24,br-1849b047c9dd 172.19.0.1/16,docker0 172.17.0.1/16,br-7e3fcfcbbbdf 172.18.0.1/16,br-e9753d63540c 172.20.0.1/16"
		],
		"GATEWAY": [
			"192.168.11.1"
		],
		"DNS": [
			"223.5.5.5"
		]
	},
	{
		"空密码用户": [
			"test"
		],
		"所有用户名": [
			"root",
			"bin",
			"daemon",
			"ntp"
		]
	},
	{
		"jdk信息": [
			"openjdk version \"1.8.0_275\"",
			"OpenJDK Runtime Environment (build 1.8.0_275-b01)",
			"OpenJDK 64-Bit Server VM (build 25.275-b01, mixed mode)"
		]
	},
	{
		"防火墙状态": [
			"not running"
		]
	},
	{
		"ssh开启状态": [
			"active"
		],
		"ssh运行情况": [
			"tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      1062/sshd           ",
			"tcp        0      0 192.168.11.127:22       192.168.11.194:50779    ESTABLISHED 10513/sshd: root@pt ",
			"tcp        0      0 192.168.11.127:22       192.168.11.194:52458    ESTABLISHED 17626/sshd: root@no ",
			"tcp6       0      0 :::22                   :::*                    LISTEN      1062/sshd           "
		]
	},
	{
		"ntp运行情况": [
			"active"
		]
	},
	{
		"docker-compose version": [
			"docker-compose version 1.29.2, build unknown"
		],
		"docker version": [
			"Docker version 20.10.0, build 7287ab3"
		],
		"docket stats": [
			"CONTAINER ID   NAME                                       CPU %     MEM USAGE / LIMIT     MEM %     NET I/O           BLOCK I/O         PIDS",
			"d36c48b5c621   sinfcloud-rabbitmq                         1.31%     122.7MiB / 15.47GiB   0.77%     3.78GB / 4.09GB   63.2MB / 2.58MB   29",
			"40db1a93ec2d   linux-command                              0.00%     144KiB / 15.47GiB     0.00%     62.1kB / 1.3MB    1.44MB / 0B       1"
		]
	}
]
# -*- coding: utf-8 -*-
"""
linux 自动化脚本
# @Time: 2022/11/4 10:20
# @Author: lln
# @File: linuxOpsStartUp.py
"""
import json
import os
import platform
import time


def runCommand(command):
    """
    执行命令,将所有读到的数据去除空行
    :param command: 命令
    :return: 去除空行后的命令
    """
    lines = os.popen(command).readlines()
    res = []
    for line in lines:
        res.append(line.replace('\n', ''))
    return res


def getSystemInfo():
    """
    使用内置库获取系统信息
    """
    res = {
        "操作系统名称及版本号": platform.platform(),
        "操作系统版本号": platform.version(),
        "操作系统的位数": platform.architecture(),
        "计算机类型": platform.machine(),
        "网络名称": platform.node(),
        "处理器信息": platform.processor(),
    }
    return res


def getSystemStatus():
    """
    系统信息,仅支持centos进行查询
    """
    # 系统
    OS = runCommand("uname -o")
    # 发行版本
    Release = runCommand("cat /etc/redhat-release 2>/dev/null")
    # 内核
    Kernel = runCommand("uname -r")
    # 主机名
    Hostname = runCommand("uname -n")
    # 当前时间
    LocalTime = runCommand("date +'%F %T'")
    # 最后启动
    LastReboot = runCommand("who -b | awk '{print $3,$4}'")
    # 运行时间
    Uptime = runCommand("date +'%F %T'")
    # 当前时区信息
    time_zone = runCommand("date -R")
    res = {
        "系统": OS,
        "发行版本": Release,
        "内核": Kernel,
        "主机名": Hostname,
        "当前时间": LocalTime,
        "最后启动": LastReboot,
        "运行时间": Uptime,
        "时区信息": time_zone
    }
    return res


def getCpuStatus():
    """
    CPU信息
    """
    # 物理CPU个数
    physical_cpus = runCommand("grep 'physical id' /proc/cpuinfo| sort | uniq | wc -l")
    # 逻辑CPU个数
    virt_cpus = runCommand("grep 'processor' /proc/cpuinfo | wc -l")
    # 每CPU核心数
    cpu_kernels = runCommand("grep 'cores' /proc/cpuinfo|uniq| awk -F ': ' '{print $2}'")
    # CPU型号
    cpu_type = runCommand("grep 'model name' /proc/cpuinfo | awk -F ': ' '{print $2}' | sort | uniq")
    # CPU架构
    cpu_arch = runCommand("uname -m")
    res = {
        '物理CPU个数': physical_cpus,
        '逻辑CPU个数': virt_cpus,
        '每CPU核心数': cpu_kernels,
        'CPU型号': cpu_type,
        'CPU架构': cpu_arch
    }
    return res


def getMemStatus():
    """
    内存信息
    """
    # 总内存
    MemTotal = runCommand("grep MemTotal /proc/meminfo| awk '{print $2}'")
    MemTotal_Num = map(float, MemTotal)[0]
    # 可用内存
    MemFree = runCommand("grep MemFree /proc/meminfo| awk '{print $2}'")
    MemFree_Num = map(float, MemFree)[0]
    # 比例
    Proportion = '{:.4%}'.format(MemFree_Num / MemTotal_Num)
    res = {
        '总内存(GB)': '{:.5}'.format(float(MemTotal_Num / 1024 / 1024)),
        '可用内存(GB)': '{:.5}'.format(float(MemFree_Num / 1024 / 1024)),
        '已用比例(%)': Proportion
    }
    return res


def getMemStatusSimple():
    MemTotal = runCommand("free -h")
    res = {
        '内存总览': MemTotal
    }
    return res


def getDiskStatus():
    """
    磁盘检查
    """
    # 生成临时数据记录文件
    # os.popen("df -TP | sed '1d' | awk '$2!='tmpfs'{print}'")
    # os.popen("df -hTP | sed 's/Mounted on/Mounted/'> /tmp/disk")
    # 硬盘总量
    DiskAllInfo = runCommand("df -h | grep -v docker")
    DiskTotal = runCommand("df -TP | sed '1d' | awk '$2!='tmpfs'{print}'| awk '{total+=$3}END{print total}'")
    DiskTotalNum = int(DiskTotal[0])
    # 硬盘使用量
    DiskUsed = runCommand("df -TP | sed '1d' | awk '$2!='tmpfs'{print}'| awk '{total+=$4}END{print total}'")
    DiskUsedNum = int(DiskUsed[0])
    # 硬盘空余量
    DiskFree = DiskTotalNum - DiskUsedNum
    # 硬盘使用比例
    DiskUsedPercent = '{:.2%}'.format(DiskUsedNum / DiskTotalNum)
    # 索引总量
    InodeTotal = runCommand("df -iTP | sed '1d' | awk '$2!='tmpfs'{print}' | awk '{total+=$3}END{print total}' ")
    InodeTotal_Num = int(InodeTotal[0])
    # 索引使用量
    InodeUsed = runCommand("df -iTP | sed '1d' | awk '$2!='tmpfs'{print}' | awk '{total+=$4}END{print total}' ")
    InodeUsed_Num = int(InodeUsed[0])
    # 索引剩余量
    InodeFree = InodeTotal_Num - InodeUsed_Num
    # 索引使用比例
    InodePercent = '{:.2%}'.format(InodeUsed_Num / InodeTotal_Num)
    res = {
        '磁盘总览': DiskAllInfo,
        '硬盘总量(GB)': int(DiskTotalNum / 1024 / 1024),
        '硬盘使用量(GB)': int(DiskUsedNum / 1024 / 1024),
        '硬盘空余量(GB)': int(DiskFree / 1024 / 1024),
        '硬盘使用比例(%)': DiskUsedPercent,
        '索引总量(MB)': int(InodeTotal_Num / 1021),
        '索引使用量(MB)': int(InodeUsed_Num / 1021),
        '索引剩余量(MB)': int(InodeFree / 1021),
        '索引使用比例(%)': InodePercent,
    }
    return res


def getNetworkStatus():
    """
    网络检查
    """
    GATEWAY = runCommand("ip route | grep default | awk '{print $3}'")
    DNS = runCommand("grep nameserver /etc/resolv.conf| grep -v '#' | awk '{print $2}' | tr '\n' ',' | sed 's/,$//'")
    IP = runCommand(
        "ip -f inet addr | grep -v 127.0.0.1 | grep inet | awk '{print $NF,$2}' | tr '\n' ',' | sed 's/,$//'")
    # TODO 语句有问题会报错,sed的错误,需要检查下执行情况
    # MAC = runCommand("ip link | grep -v 'LOOPBACK\|loopback' | awk '{print $2}' | sed 'N;s/\n//' | tr '\n' ',' | sed 's/,$//'")
    res = {
        'GATEWAY': GATEWAY,
        'DNS': DNS,
        'IP': IP
        # 'MAC': MAC
    }
    return res


def getUserStatus():
    """
    所有用户和空密码用户
    """
    all_user = runCommand("awk -F':' '{ print $1}' /etc/passwd")
    empty_passwd_user = runCommand("getent shadow | grep -Po '^[^:]*(?=::)'")
    res = {
        '所有用户名': all_user,
        '空密码用户': empty_passwd_user
    }
    return res


def getJdkStatus():
    """
    jdk信息
    """
    jdkInfo = runCommand("java -version 2>&1")
    res = {
        'jdk信息': jdkInfo
    }
    return res


def getFirewallStatus():
    """
    防火墙
    """
    firewall = runCommand("firewall-cmd --state 2>&1")
    # 兼容 ubuntu 防火墙命令报错 sh: not found 特殊处理
    for info in firewall:
        if "not found" in info:
            firewall = runCommand("ufw status")
    res = {
        '防火墙状态': firewall
    }
    return res


def sshStatus():
    """
    ssh 检查
    """
    sshActive = runCommand("systemctl is-active sshd.service")
    sshNetstat = runCommand("sudo netstat -atlunp | grep sshd")
    res = {
        'ssh开启状态': sshActive,
        'ssh运行情况': sshNetstat
    }
    return res


def ntpStatus():
    """
    ntp 检查
    """
    ntpActive = runCommand("systemctl is-active ntpd")
    res = {
        'ntp运行情况': ntpActive
    }
    return res


def dockerStatus():
    """
    docker 检查
    """
    dk_version = runCommand("docker -v")
    dk_stats = []
    for info in dk_version:
        if "version" not in info:
            dk_version = "未安装docker"
        else:
            lines = os.popen(
                "docker stats --all --no-stream").readlines()
            for line in lines:
                dk_stats.append(line.replace('\n', ''))
    dp_version = runCommand("docker-compose --version")
    for info in dp_version:
        if "version" not in info:
            dp_version = "未安装docker-compose"
    res = {
        'docker version': dk_version,
        'docker-compose version': dp_version,
        'docker stats': dk_stats
    }
    return res


def createReportFile(name, text):
    """
    创建report的txt文件,并写入数据
    """
    report_dir = os.getcwd() + os.sep + "report" + os.sep
    # 判断当前路径是否存在,没有则创建new文件夹
    if not os.path.exists(report_dir):
        os.makedirs(report_dir)
    # 在当前py文件所在路径下的new文件中创建txt
    report_file = report_dir + name + '.txt'
    # 打开文件,open()函数用于打开一个文件,创建一个file对象,相关的方法才可以调用它进行读写。
    file = open(report_file, 'w')
    # 写入内容信息
    file.write(text)
    file.close()
    print('report_file create success', report_file)


def printSinfcloud():
    print("+------------------------------------------------+")
    print("|       欢迎使用SinfCloud自动巡检工具            |")
    print("| ____  _        __  ____ _                 _    |")
    print("|/ ___|(_)_ __  / _|/ ___| | ___  _   _  __| |   |")
    print("|\___ \| |  _ \| |_| |   | |/ _ \| | | |/ _  |   |")
    print("| ___) | | | | |  _| |___| | (_) | |_| | (_| |   |")
    print("||____/|_|_| |_|_|  \____|_|\___/ \__,_|\__,_|   |")
    print("|                                                |")
    print("+------------------------------------------------+")


if __name__ == '__main__':
    printSinfcloud()
    outputFileName = time.strftime('%Y-%m-%d', time.localtime(time.time())) + "_report"
    report = list()
    report.append(getSystemInfo())
    report.append(getSystemStatus())
    report.append(getCpuStatus())
    report.append(getMemStatusSimple())
    report.append(getDiskStatus())
    report.append(getNetworkStatus())
    report.append(getUserStatus())
    report.append(getJdkStatus())
    report.append(getFirewallStatus())
    report.append(sshStatus())
    report.append(ntpStatus())
    report.append(dockerStatus())
    createReportFile(outputFileName,
                     json.dumps(report, sort_keys=True, indent=4, separators=(',', ':'), ensure_ascii=False))

Guess you like

Origin blog.csdn.net/weixin_42559985/article/details/129987875