2025-03-17 18:06:54 +08:00

393 lines
14 KiB
Python

#!/bin/python
# coding: utf-8
# +-------------------------------------------------------------------
# | django-vue-lyadmin
# +-------------------------------------------------------------------
# | Author: lybbn
# +-------------------------------------------------------------------
# | QQ: 1042594286
# +-------------------------------------------------------------------
# ------------------------------
# linux系统命令工具类封装
# ------------------------------
import os, sys, re, time, json
import psutil
from django.core.cache import cache
from config import EXEC_LOG_PATH
from pathlib import Path
import subprocess
import platform
BASE_DIR = Path(__file__).resolve().parent
def md5(strings):
"""
@name 生成md5
@param strings 要被处理的字符串
@return string(32)
"""
if type(strings) != bytes:
strings = strings.encode()
import hashlib
m = hashlib.md5()
m.update(strings)
return m.hexdigest()
def WriteLog(logMsg):
"""
写日志
"""
try:
with open(EXEC_LOG_PATH, 'w+') as f:
f.write(logMsg)
f.close()
except:
pass
def GetSystemVersion():
"""
取操作系统版本
"""
key = 'lybbn_sys_version'
version = cache.get(key)
if version: return version
try:
# Python 3.8 已移除 此方法 "linux_distribution()"
platform_dist = platform.linux_distribution()
version = platform_dist[0] + " " + platform_dist[1]
except:
with os.popen("cat /etc/redhat-release", "r") as p:
release = p.read()
version = release.replace('release ', '').replace('Linux', '').replace('(Core)', '').strip()
pyv_info = sys.version_info
version = "{} {}(Py{}.{}.{})".format(version, os.uname().machine, pyv_info.major, pyv_info.minor, pyv_info.micro)
cache.set(key, version, 86400)
return version
def GetLoadAverage():
"""
取系统负载
"""
try:
c = os.getloadavg()
except:
c = [0, 0, 0]
data = {}
data['one'] = float(c[0])
data['five'] = float(c[1])
data['fifteen'] = float(c[2])
data['max'] = psutil.cpu_count() * 2
data['limit'] = data['max']
data['safe'] = data['max'] * 0.75
temppercent = round(data['one'] / data['max'] * 100)
data['percent'] = 100 if temppercent > 100 else temppercent
return data
def GetMemInfo():
"""
取内存信息
"""
mem = psutil.virtual_memory()
memInfo = {}
memInfo2 = {'memTotal': int(mem.total / 1024 / 1024), 'memFree': int(mem.free / 1024 / 1024),
'memBuffers': int(mem.buffers / 1024 / 1024), 'memCached': int(mem.cached / 1024 / 1024)}
memInfo['total'] = round(float(mem.total) / 1024 / 1024 / 1024, 2)
memInfo['free'] = round((memInfo2['memFree'] + memInfo2['memBuffers'] + memInfo2['memCached']) / 1024, 2)
memInfo['used'] = round(float(mem.used) / 1024 / 1024 / 1024, 2)
memInfo['percent'] = round((int(mem.used) / 1024 / 1024) / memInfo2['memTotal'] * 100, 1)
return memInfo
def get_disk_iostat():
"""
获取磁盘IO
"""
iokey = 'iostat'
diskio = cache.get(iokey)
mtime = int(time.time())
if not diskio:
diskio = {}
diskio['info'] = None
diskio['time'] = mtime
diskio_1 = diskio['info']
stime = mtime - diskio['time']
if not stime: stime = 1
diskInfo = {}
diskInfo['ALL'] = {}
diskInfo['ALL']['read_count'] = 0
diskInfo['ALL']['write_count'] = 0
diskInfo['ALL']['read_bytes'] = 0
diskInfo['ALL']['write_bytes'] = 0
diskInfo['ALL']['read_time'] = 0
diskInfo['ALL']['write_time'] = 0
diskInfo['ALL']['read_merged_count'] = 0
diskInfo['ALL']['write_merged_count'] = 0
try:
if os.path.exists('/proc/diskstats'):
diskio_2 = psutil.disk_io_counters(perdisk=True)
if not diskio_1:
diskio_1 = diskio_2
for disk_name in diskio_2.keys():
diskInfo[disk_name] = {}
diskInfo[disk_name]['read_count'] = int(
(diskio_2[disk_name].read_count - diskio_1[disk_name].read_count) / stime)
diskInfo[disk_name]['write_count'] = int(
(diskio_2[disk_name].write_count - diskio_1[disk_name].write_count) / stime)
diskInfo[disk_name]['read_bytes'] = int(
(diskio_2[disk_name].read_bytes - diskio_1[disk_name].read_bytes) / stime)
diskInfo[disk_name]['write_bytes'] = int(
(diskio_2[disk_name].write_bytes - diskio_1[disk_name].write_bytes) / stime)
diskInfo[disk_name]['read_time'] = int(
(diskio_2[disk_name].read_time - diskio_1[disk_name].read_time) / stime)
diskInfo[disk_name]['write_time'] = int(
(diskio_2[disk_name].write_time - diskio_1[disk_name].write_time) / stime)
diskInfo[disk_name]['read_merged_count'] = int(
(diskio_2[disk_name].read_merged_count - diskio_1[disk_name].read_merged_count) / stime)
diskInfo[disk_name]['write_merged_count'] = int(
(diskio_2[disk_name].write_merged_count - diskio_1[disk_name].write_merged_count) / stime)
diskInfo['ALL']['read_count'] += diskInfo[disk_name]['read_count']
diskInfo['ALL']['write_count'] += diskInfo[disk_name]['write_count']
diskInfo['ALL']['read_bytes'] += diskInfo[disk_name]['read_bytes']
diskInfo['ALL']['write_bytes'] += diskInfo[disk_name]['write_bytes']
if diskInfo['ALL']['read_time'] < diskInfo[disk_name]['read_time']:
diskInfo['ALL']['read_time'] = diskInfo[disk_name]['read_time']
if diskInfo['ALL']['write_time'] < diskInfo[disk_name]['write_time']:
diskInfo['ALL']['write_time'] = diskInfo[disk_name]['write_time']
diskInfo['ALL']['read_merged_count'] += diskInfo[disk_name]['read_merged_count']
diskInfo['ALL']['write_merged_count'] += diskInfo[disk_name]['write_merged_count']
cache.set(iokey, {'info': diskio_2, 'time': mtime})
except:
return diskInfo
return diskInfo
def GetNetWork():
"""
取网卡数据
"""
cache_timeout = 86400
otime = cache.get("lybbn_otime")
ntime = time.time()
networkInfo = {}
networkInfo['network'] = {}
networkInfo['upTotal'] = 0
networkInfo['downTotal'] = 0
networkInfo['up'] = 0
networkInfo['down'] = 0
networkInfo['downPackets'] = 0
networkInfo['upPackets'] = 0
networkIo_list = psutil.net_io_counters(pernic=True)
for net_key in networkIo_list.keys():
networkIo = networkIo_list[net_key][:4]
up_key = "{}_up".format(net_key)
down_key = "{}_down".format(net_key)
otime_key = "lybbn_otime"
if not otime:
otime = time.time()
cache.set(up_key, networkIo[0], cache_timeout)
cache.set(down_key, networkIo[1], cache_timeout)
cache.set(otime_key, otime, cache_timeout)
networkInfo['network'][net_key] = {}
up = cache.get(up_key)
down = cache.get(down_key)
if not up:
up = networkIo[0]
if not down:
down = networkIo[1]
networkInfo['network'][net_key]['upTotal'] = networkIo[0]
networkInfo['network'][net_key]['downTotal'] = networkIo[1]
networkInfo['network'][net_key]['up'] = round(float(networkIo[0] - up) / 1024 / (ntime - otime), 2)
networkInfo['network'][net_key]['down'] = round(float(networkIo[1] - down) / 1024 / (ntime - otime), 2)
networkInfo['network'][net_key]['downPackets'] = networkIo[3]
networkInfo['network'][net_key]['upPackets'] = networkIo[2]
networkInfo['upTotal'] += networkInfo['network'][net_key]['upTotal']
networkInfo['downTotal'] += networkInfo['network'][net_key]['downTotal']
networkInfo['up'] += networkInfo['network'][net_key]['up']
networkInfo['down'] += networkInfo['network'][net_key]['down']
networkInfo['downPackets'] += networkInfo['network'][net_key]['downPackets']
networkInfo['upPackets'] += networkInfo['network'][net_key]['upPackets']
cache.set(up_key, networkIo[0], cache_timeout)
cache.set(down_key, networkIo[1], cache_timeout)
cache.set(otime_key, time.time(), cache_timeout)
networkInfo['up'] = round(float(networkInfo['up']), 2)
networkInfo['down'] = round(float(networkInfo['down']), 2)
networkInfo['iostat'] = get_disk_iostat()
return networkInfo
def GetBootTime():
"""
取系统启动时间(天)
"""
key = 'lybbn_sys_time'
sys_time = cache.get(key)
if sys_time: return sys_time
uptime_seconds = time.mktime(time.localtime(time.time())) - psutil.boot_time()
run_days = int(uptime_seconds / 86400)
# run_hour = int((uptime_seconds % 86400) / 3600)
# run_minute = int((uptime_seconds % 3600) / 60)
# run_second = int(uptime_seconds % 60)
sys_time = "{}".format(run_days)
cache.set(key, sys_time, 1800)
return sys_time
def getCpuInfoDict():
"""
取/proc/cpuinfo信息字典
"""
cpuinfo = {}
procinfo = {}
nprocs = 0
with open('/proc/cpuinfo') as f:
for line in f:
if not line.strip():
cpuinfo['proc%s' % nprocs] = procinfo
nprocs = nprocs + 1
procinfo = {}
else:
if len(line.split(':')) == 2:
procinfo[line.split(':')[0].strip()] = line.split(':')[1].strip()
else:
procinfo[line.split(':')[0].strip()] = ''
return cpuinfo
def GetCpuInfo(interval=1):
"""
取CPU信息
"""
cpuCount = cache.get('lybbn_cpu_cpuCount')
if not cpuCount:
cpuCount = psutil.cpu_count()
cache.set('lybbn_cpu_cpuCount', cpuCount, 86400)
cpuNum = cache.get('lybbn_cpu_cpuNum')
if not cpuNum:
cpuNum = psutil.cpu_count(logical=False)
cache.set('lybbn_cpu_cpuNum', cpuNum, 86400)
cpuW = cache.get('lybbn_cpu_cpuW')
if not cpuW:
cpuW = int(subprocess.check_output('cat /proc/cpuinfo | grep "physical id" | sort -u | wc -l', shell=True))
cache.set('lybbn_cpu_cpuW', cpuW, 86400)
used = psutil.cpu_percent(interval)
used_all = psutil.cpu_percent(percpu=True)
cpu_name = cache.get('lybbn_cpu_cpu_name')
if not cpu_name:
cpu_name = ""
try:
cpuinfo = getCpuInfoDict()
cpu_name = cpuinfo['proc0']['model name'] + " * {}".format(cpuW)
except:
pass
cache.set('lybbn_cpu_cpu_name', cpu_name, 86400)
return used, cpuCount, used_all, cpu_name, cpuNum, cpuW
def GetDiskInfo():
# 取磁盘分区信息
key = 'lybbn_sys_disk'
diskInfo = cache.get(key)
if diskInfo: return diskInfo
with os.popen("df -hT -P|grep '/'|grep -v tmpfs|grep -v 'snap/core'|grep -v udev", "r") as p:
temp = p.read()
with os.popen("df -i -P|grep '/'|grep -v tmpfs|grep -v 'snap/core'|grep -v udev", "r") as p:
tempInodes = p.read()
tempList = temp.split('\n')
tempInodesList = tempInodes.split('\n')
diskInfo = []
n = 0
cuts = ['/mnt/cdrom', '/boot', '/boot/efi', '/dev', '/dev/shm', '/run/lock', '/run', '/run/shm', '/run/user']
for tmp in tempList:
n += 1
try:
inodes = tempInodesList[n - 1].split()
disk = re.findall(r"^(.+)\s+([\w\.]+)\s+([\w\.]+)\s+([\w\.]+)\s+([\w\.]+)\s+([\d%]{2,4})\s+(/.{0,100})$",
tmp.strip())
if disk: disk = disk[0]
if len(disk) < 6: continue
if disk[2].find('M') != -1: continue
if disk[2].find('K') != -1: continue
if len(disk[6].split('/')) > 10: continue
if disk[6] in cuts: continue
if disk[6].find('docker') != -1: continue
if disk[1].strip() in ['tmpfs']: continue
arr = {}
arr['filesystem'] = disk[0].strip()
arr['type'] = disk[1].strip()
arr['path'] = disk[6]
tmp1 = [disk[2], disk[3], disk[4], disk[5].split('%')[0]]
arr['size'] = tmp1
arr['inodes'] = [inodes[1], inodes[2], inodes[3], inodes[4]]
diskInfo.append(arr)
except Exception as ex:
WriteLog('获取磁盘信息失败:%s' % str(ex))
continue
cache.set(key, diskInfo, 1000)
return diskInfo
def GetFileLastNumsLines(path,num=1000):
"""
获取指定文件的指定尾行数内容
"""
try:
if not os.path.exists(path): return ""
filesize = os.path.getsize(path)
if filesize == 0: return ""
num = int(num)
total_lines_wanted = num
BLOCK_SIZE = 4096
with open(path,"rb") as f:
f.seek(0, 2)
block_end_byte = f.tell()
lines_to_go = total_lines_wanted
block_number = -1
blocks = []
while lines_to_go > 0 and block_end_byte > 0:
if (block_end_byte - BLOCK_SIZE > 0):
f.seek(block_number*BLOCK_SIZE, 2)
blocks.append(f.read(BLOCK_SIZE))
else:
f.seek(0,0)
blocks.append(f.read(block_end_byte))
lines_found = blocks[-1].count(b'\n')
lines_to_go -= lines_found
block_end_byte -= BLOCK_SIZE
block_number -= 1
all_read_text = b''.join(reversed(blocks))
return b'\n'.join(all_read_text.splitlines()[-total_lines_wanted:])
except:
return ""
def RestartServer():
"""
重启系统
"""
try:
os.system("sync && init 6 &")
except:
pass