代码
# coding:utf-8
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,
}
# 将系统信息转换为 JSON 格式并发送给客户端
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:
# 设置响应的状态码为404
self.send_response(404)
self.send_header('Content-type', 'text/html')
self.end_headers()
# 输出404错误页面
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
# 运行 HTTP 服务器
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代码
<!--suppress SpellCheckingInspection -->
<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) // 每1秒更新一次数据
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>
预览图