代码
import http.server
import json
import psutil
import socket
import platform
import multiprocessing
import os
def get_network_info ():
import psutil
interfaces = psutil.net_if_addrs()
network_info = {}
for interface_name, interface_addresses in interfaces.items():
addresses = []
for address in interface_addresses:
addresses.append({
'family' : address.family.name,
'address' : address.address,
'netmask' : address.netmask,
'broadcast' : address.broadcast
})
network_info[interface_name] = addresses
return network_info
def get_system_info ():
system_info = {
'system' : platform.system(),
'hostname' : socket.gethostname(),
'release' : platform.release(),
'version' : platform.version(),
'machine' : platform.machine(),
'cpu' : get_cpu(),
'ip_address' : socket.gethostbyname(socket.gethostname()),
'platform' : platform.platform(),
}
return system_info
def get_cpu ():
model = None
try :
with open ('/proc/cpuinfo' , 'r' ) as f:
for line in f:
if line.strip().startswith('model name' ):
model = line.split(':' )[1 ].strip()
break
cores = multiprocessing.cpu_count()
threads = os.cpu_count()
return {
'model' : model,
'cores' : cores,
'threads' : threads
}
except Exception as e:
print ("Error while retrieving CPU model:" , e)
return None
class SimpleHTTPRequestHandler (http.server.BaseHTTPRequestHandler):
def do_GET (self ):
if self.path == '/' :
self.send_response(200 )
self.send_header('Content-type' , 'application/json' )
self.end_headers()
cpu_usage = self.get_cpu_usage()
total_memory, used_memory = self.get_memory_usage()
total_disk_space, used_disk_space = self.get_disk_usage()
system_info = {
'cpu_usage' : cpu_usage,
'memory_total' : total_memory,
'memory_used' : used_memory,
'disk_space_total' : total_disk_space,
'disk_space_free' : used_disk_space,
}
self.wfile.write(json.dumps(system_info).encode('utf-8' ))
elif self.path == '/detail' :
self.send_response(200 )
self.send_header('Content-type' , 'application/json' )
self.end_headers()
detail = {
'network_info' : get_network_info(),
'system_info' : get_system_info(),
}
self.wfile.write(json.dumps(detail).encode('utf-8' ))
else :
self.send_response(404 )
self.send_header('Content-type' , 'text/html' )
self.end_headers()
response_content = b"<html><head><title>404 Not Found</title></head>"
response_content += b"<body><h1>404 Not Found</h1></body></html>"
self.wfile.write(response_content)
def get_cpu_usage (self ):
return psutil.cpu_percent(interval=0.5 )
def get_memory_usage (self ):
total_memory = psutil.virtual_memory().total
used_memory = psutil.virtual_memory().used
return total_memory, used_memory
def get_disk_usage (self ):
total_disk_space = psutil.disk_usage('/' ).total
used_disk_space = psutil.disk_usage('/' ).used
return total_disk_space, total_disk_space - used_disk_space
def run ():
port = 9999
server_address = ('' , port)
httpd = http.server.HTTPServer(server_address, SimpleHTTPRequestHandler)
print (f'HTTP 服务器已启动... 端口: {port} ' )
httpd.serve_forever()
if __name__ == '__main__' :
run()
输出样式:
使用率等信息:
{ "cpu_usage" : 1.0 , "memory_total" : 3875471360 , "memory_used" : 1179262976 , "disk_space_total" : 53660876800 , "disk_space_free" : 39212634112 }
系统详细信息
{ "network_info" : { "lo" : [ { "family" : "AF_INET" , "address" : "127.0.0.1" , "netmask" : "255.0.0.0" , "broadcast" : null } , { "family" : "AF_INET6" , "address" : "::1" , "netmask" : "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff" , "broadcast" : null } , { "family" : "AF_PACKET" , "address" : "00:00:00:00:00:00" , "netmask" : null , "broadcast" : null } ] , "eno1" : [ { "family" : "AF_INET" , "address" : "192.168.0.3" , "netmask" : "255.255.255.0" , "broadcast" : "192.168.0.255" } , { "family" : "AF_INET6" , "address" : "2409:8a60:1e93:c471:3fa5:3e98:c502:c183" , "netmask" : "ffff:ffff:ffff:ffff::" , "broadcast" : null } , { "family" : "AF_INET6" , "address" : "fe80::ae23:d9:8c71:4bd5%eno1" , "netmask" : "ffff:ffff:ffff:ffff::" , "broadcast" : null } , { "family" : "AF_PACKET" , "address" : "00:23:24:bc:c3:95" , "netmask" : null , "broadcast" : "ff:ff:ff:ff:ff:ff" } ] , "docker0" : [ { "family" : "AF_INET" , "address" : "172.17.0.1" , "netmask" : "255.255.0.0" , "broadcast" : "172.17.255.255" } , { "family" : "AF_PACKET" , "address" : "02:42:04:d1:02:ae" , "netmask" : null , "broadcast" : "ff:ff:ff:ff:ff:ff" } ] , "virbr0" : [ { "family" : "AF_INET" , "address" : "192.168.122.1" , "netmask" : "255.255.255.0" , "broadcast" : "192.168.122.255" } , { "family" : "AF_PACKET" , "address" : "52:54:00:5d:e5:60" , "netmask" : null , "broadcast" : "ff:ff:ff:ff:ff:ff" } ] , "vmnet1" : [ { "family" : "AF_INET" , "address" : "192.168.43.1" , "netmask" : "255.255.255.0" , "broadcast" : "192.168.43.255" } , { "family" : "AF_INET6" , "address" : "fe80::250:56ff:fec0:1%vmnet1" , "netmask" : "ffff:ffff:ffff:ffff::" , "broadcast" : null } , { "family" : "AF_PACKET" , "address" : "00:50:56:c0:00:01" , "netmask" : null , "broadcast" : "ff:ff:ff:ff:ff:ff" } ] , "vmnet8" : [ { "family" : "AF_INET" , "address" : "192.168.128.1" , "netmask" : "255.255.255.0" , "broadcast" : "192.168.128.255" } , { "family" : "AF_INET6" , "address" : "fe80::250:56ff:fec0:8%vmnet8" , "netmask" : "ffff:ffff:ffff:ffff::" , "broadcast" : null } , { "family" : "AF_PACKET" , "address" : "00:50:56:c0:00:08" , "netmask" : null , "broadcast" : "ff:ff:ff:ff:ff:ff" } ] , "virbr0-nic" : [ { "family" : "AF_PACKET" , "address" : "52:54:00:5d:e5:60" , "netmask" : null , "broadcast" : "ff:ff:ff:ff:ff:ff" } ] } , "system_info" : { "system" : "Linux" , "release" : "3.10.0-1160.90.1.el7.x86_64" , "version" : "#1 SMP Thu May 4 15:21:22 UTC 2023" , "machine" : "x86_64" , "cpu" : { "model" : "Intel(R) Core(TM) i3-4360T CPU @ 3.20GHz" , "cores" : 4 , "threads" : 4 } , "hostname" : "lenovo-m73" , "ip_address" : "192.168.0.3" , "platform" : "Linux-3.10.0-1160.90.1.el7.x86_64-x86_64-with-centos-7.9.2009-Core" } }
Vue代码
<template >
<div class ="dashboard-container" >
<div class ="dashboard-editor-container" >
<el-row class ="panel-group" style ="margin-left: -20px;margin-right: -20px;" >
<el-col :xs ="12" :sm ="12" :lg ="8" class ="card-panel-col" >
<div class ="card-panel" >
<p class ="chart-title" > CPU使用率</p >
<div ref ="cpuChart" class ="chart" />
</div >
</el-col >
<el-col :xs ="12" :sm ="12" :lg ="8" class ="card-panel-col" >
<div class ="card-panel" >
<p class ="chart-title" > 内存使用率</p >
<div ref ="memoryChart" class ="chart" />
</div >
</el-col >
<el-col :xs ="12" :sm ="12" :lg ="8" class ="card-panel-col" >
<div class ="card-panel" >
<p class ="chart-title" > 系统磁盘</p >
<div ref ="diskChart" class ="chart" />
</div >
</el-col >
</el-row >
</div >
<div >
<el-row >
<el-col :xs ="12" :sm ="12" :lg ="8" >
<el-card >
<h3 slot ="header" > 系统信息</h3 >
<el-table :show-header ="false" :data ="systemInfo" stripe style ="width: 100%" >
<el-table-column prop ="key" label ="属性" >
<template slot-scope ="scope" >
<b > {{ scope.row.key }}</b >
</template >
</el-table-column >
<el-table-column prop ="value" label ="值" />
</el-table >
</el-card >
</el-col >
<el-col :xs ="12" :sm ="12" :lg ="16" >
<el-card >
<h3 slot ="header" > 网络接口</h3 >
<el-collapse >
<el-collapse-item v-for ="(interfaces, interfaceName) in networkInfo" :key ="interfaceName" >
<template slot ="title" >
<span style ="font-weight: bold" > {{ interfaceName }}</span >
</template >
<el-table :data ="interfaces" stripe style ="width: 100%" >
<el-table-column prop ="family" label ="地址类型" />
<el-table-column prop ="address" label ="地址" />
<el-table-column prop ="netmask" label ="子网掩码" />
<el-table-column prop ="broadcast" label ="广播地址" />
</el-table >
</el-collapse-item >
</el-collapse >
</el-card >
</el-col >
</el-row >
</div >
</div >
</template >
<script >
import echarts from 'echarts'
export default {
data ( ) {
return {
sysInfo : {
cpuUsage : 0 ,
memoryTotal : 0 ,
memoryUsed : 0 ,
diskSpaceTotal : 0 ,
diskUsage : 0 ,
},
networkInfo : {},
systemInfo : [],
}
},
mounted ( ) {
this .fetchSysInfo ()
setInterval (this .fetchSysInfo , 2000 )
this .getSysDetail ()
},
methods : {
getSysDetail ( ) {
fetch ('/api/sysinfo/detail' )
.then (response => response.json ())
.then (data => {
this .networkInfo = data.network_info
const systemInfo = data.system_info
this .systemInfo = [
{ key : '系统' , value : systemInfo.system },
{ key : '发行版' , value : systemInfo.release },
{ key : '版本' , value : systemInfo.version },
{ key : '机器类型' , value : systemInfo.machine },
{ key : 'CPU型号' , value : systemInfo.cpu .model },
{ key : 'CPU核心数' , value : systemInfo.cpu .cores },
{ key : 'CPU线程数' , value : systemInfo.cpu .threads },
{ key : '主机名' , value : systemInfo.hostname },
{ key : 'IP地址' , value : systemInfo.ip_address },
{ key : '平台' , value : systemInfo.platform },
]
})
},
fetchSysInfo ( ) {
fetch ('/api/sysinfo' )
.then (response => response.json ())
.then (data => {
this .sysInfo .cpuUsage = data.cpu_usage
this .sysInfo .memoryTotal = data.memory_total
this .sysInfo .memoryUsed = data.memory_used
this .sysInfo .diskSpaceTotal = data.disk_space_total
this .sysInfo .diskSpaceFree = data.disk_space_free
this .updateCharts ()
})
.catch (error => {
console .error ('Error fetching system info:' , error)
})
},
updateCharts ( ) {
this .updateCPUChart ()
this .updateMemoryChart ()
this .updateDiskChart ()
},
updateCPUChart ( ) {
const cpuChart = echarts.init (this .$refs .cpuChart )
const option = {
series : [
{
type : 'gauge' ,
detail : { formatter : '{value}%' , offsetCenter : [0 , '70%' ] },
data : [{ value : this .sysInfo .cpuUsage }],
},
],
graphic : [
{
type : 'text' ,
left : 'center' ,
bottom : 12 ,
style : {
text : 'CPU 占用率' ,
textAlign : 'center' ,
fill : '#333' ,
fontSize : 18
},
},
],
}
cpuChart.setOption (option)
},
updateMemoryChart ( ) {
const memoryChart = echarts.init (this .$refs .memoryChart )
const memoryUsage = (this .sysInfo .memoryTotal === 0 ) ? 0 : (this .sysInfo .memoryUsed / this .sysInfo .memoryTotal ).toFixed (2 ) * 100
const option = {
series : [
{
type : 'gauge' ,
detail : { formatter : '{value}%' , offsetCenter : [0 , '70%' ] },
data : [{ value : memoryUsage }],
},
],
graphic : [
{
type : 'text' ,
left : 'center' ,
bottom : 12 ,
style : {
text : '内存 占用率' ,
textAlign : 'center' ,
fill : '#333' ,
fontSize : 18
},
},
],
}
memoryChart.setOption (option)
},
updateDiskChart ( ) {
const diskChart = echarts.init (this .$refs .diskChart )
const diskUsage = (this .sysInfo .diskSpaceTotal === 0 ) ? 0 : ((this .sysInfo .diskSpaceTotal - this .sysInfo .diskSpaceFree ) / this .sysInfo .diskSpaceTotal ).toFixed (2 ) * 100
const option = {
series : [
{
type : 'gauge' ,
detail : { formatter : '{value}%' , offsetCenter : [0 , '70%' ] },
data : [{ value : diskUsage }],
},
],
graphic : [
{
type : 'text' ,
left : 'center' ,
bottom : 12 ,
style : {
text : '系统盘 占用率' ,
textAlign : 'center' ,
fill : '#333' ,
fontSize : 18
},
},
],
}
diskChart.setOption (option)
},
},
}
</script >
<style lang ="scss" scoped >
.dashboard-editor-container {
padding : 32px ;
background-color : rgb (240 , 242 , 245 );
position : relative;
.panel-group {
margin-top : 18px ;
.card-panel-col {
margin-bottom : 32px ;
padding-left : 20px ;
padding-right : 20px ;
}
.card-panel {
height : 240px ;
cursor : pointer;
font-size : 12px ;
position : relative;
overflow : hidden;
color : #666 ;
//background : #fff ;
box-shadow : 4px 4px 40px rgba (0 , 0 , 0 , .05 );
border-color : rgba (0 , 0 , 0 , .05 );
.chart-title {
position : absolute;
left : 12px ;
top : 0 ;
font-size : 14px ;
}
.chart {
height : 240px ;
}
}
}
.github-corner {
position : absolute;
top : 0 ;
border : 0 ;
right : 0 ;
}
.chart-wrapper {
background : #fff ;
padding : 16px 16px 0 ;
margin-bottom : 32px ;
}
}
@media (max-width :1024px ) {
.chart-wrapper {
padding : 8px ;
}
}
</style >
预览图
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理