427 lines
15 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.

#!/bin/python
# coding: utf-8
# +-------------------------------------------------------------------
# | django-vue-lyadmin
# +-------------------------------------------------------------------
# | Author: lybbn
# +-------------------------------------------------------------------
# | QQ: 1042594286
# +-------------------------------------------------------------------
# ------------------------------
# linux系统命令工具类封装
# ------------------------------
import pwd
import grp
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
def GetUidName(file_path,uid=0):
"""
通过系统uid获取对应名称
"""
try:
return pwd.getpwuid(uid).pw_name
except Exception as e:
return ""
def GetGroupidName(file_path,gid=0):
"""
通过系统goup id所属组id获取对应名称
"""
try:
return grp.getgrgid(gid).gr_name
except Exception as e:
return ""
def ForceRemoveDir(directory):
"""
强制删除目录
"""
sys_dir = ['/root','/','/proc','/*','/root/*']
if directory in sys_dir:
raise ValueError("受保护的目录,无法删除!!!")
if os.path.exists(directory):
try:
# 执行 rm -rf 命令
subprocess.run(['rm', '-rf', directory], check=True)
except subprocess.CalledProcessError as e:
raise ValueError(f"强制删除目录错误: {e}")