111 lines
3.0 KiB
Go
111 lines
3.0 KiB
Go
package main
|
||
|
||
import (
|
||
"os"
|
||
"os/exec"
|
||
"strconv"
|
||
"strings"
|
||
"time"
|
||
)
|
||
|
||
// readNetworkInterfaces 读取网络接口信息(包含瞬时流量速度) - 优化版:所有接口并行采样
|
||
func readNetworkInterfaces() []NetworkInterface {
|
||
interfaces := []NetworkInterface{}
|
||
|
||
// 读取网络接口列表
|
||
entries, err := os.ReadDir("/sys/class/net")
|
||
if err != nil {
|
||
return interfaces
|
||
}
|
||
|
||
// 收集要监控的接口名称
|
||
var validIfaces []string
|
||
for _, entry := range entries {
|
||
ifName := entry.Name()
|
||
if ifName == "lo" { // 跳过回环接口
|
||
continue
|
||
}
|
||
|
||
// 跳过 Docker 相关网络接口
|
||
if strings.HasPrefix(ifName, "docker") ||
|
||
strings.HasPrefix(ifName, "br-") ||
|
||
strings.HasPrefix(ifName, "veth") {
|
||
continue
|
||
}
|
||
|
||
validIfaces = append(validIfaces, ifName)
|
||
}
|
||
|
||
// 第一次批量读取所有接口的流量
|
||
firstReadings := make(map[string][2]uint64) // [rx, tx]
|
||
for _, ifName := range validIfaces {
|
||
rxPath := "/sys/class/net/" + ifName + "/statistics/rx_bytes"
|
||
txPath := "/sys/class/net/" + ifName + "/statistics/tx_bytes"
|
||
|
||
var rxBytes, txBytes uint64
|
||
if rxStr := readFirstLine(rxPath); rxStr != "" {
|
||
rxBytes, _ = strconv.ParseUint(strings.TrimSpace(rxStr), 10, 64)
|
||
}
|
||
if txStr := readFirstLine(txPath); txStr != "" {
|
||
txBytes, _ = strconv.ParseUint(strings.TrimSpace(txStr), 10, 64)
|
||
}
|
||
firstReadings[ifName] = [2]uint64{rxBytes, txBytes}
|
||
}
|
||
|
||
// 等待500ms(所有接口一起等待,而不是每个接口单独等待)
|
||
time.Sleep(500 * time.Millisecond)
|
||
|
||
// 第二次批量读取并构建结果
|
||
for _, ifName := range validIfaces {
|
||
iface := NetworkInterface{
|
||
Name: ifName,
|
||
}
|
||
|
||
// 读取 MAC 地址
|
||
macPath := "/sys/class/net/" + ifName + "/address"
|
||
iface.MACAddress = strings.TrimSpace(readFirstLine(macPath))
|
||
|
||
// 读取 IP 地址 (使用 ip addr show)
|
||
cmd := exec.Command("ip", "addr", "show", ifName)
|
||
if out, err := cmd.Output(); err == nil {
|
||
lines := strings.Split(string(out), "\n")
|
||
for _, line := range lines {
|
||
line = strings.TrimSpace(line)
|
||
if strings.HasPrefix(line, "inet ") {
|
||
fields := strings.Fields(line)
|
||
if len(fields) >= 2 {
|
||
iface.IPAddress = strings.Split(fields[1], "/")[0]
|
||
break
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
// 读取第二次流量统计
|
||
rxPath := "/sys/class/net/" + ifName + "/statistics/rx_bytes"
|
||
txPath := "/sys/class/net/" + ifName + "/statistics/tx_bytes"
|
||
|
||
var rxBytes2, txBytes2 uint64
|
||
if rxStr := readFirstLine(rxPath); rxStr != "" {
|
||
rxBytes2, _ = strconv.ParseUint(strings.TrimSpace(rxStr), 10, 64)
|
||
}
|
||
if txStr := readFirstLine(txPath); txStr != "" {
|
||
txBytes2, _ = strconv.ParseUint(strings.TrimSpace(txStr), 10, 64)
|
||
}
|
||
|
||
// 设置累计流量
|
||
iface.RxBytes = rxBytes2
|
||
iface.TxBytes = txBytes2
|
||
|
||
// 计算瞬时速度 (bytes/s,乘以2因为采样间隔是0.5秒)
|
||
if first, ok := firstReadings[ifName]; ok {
|
||
iface.RxSpeed = float64(rxBytes2-first[0]) * 2
|
||
iface.TxSpeed = float64(txBytes2-first[1]) * 2
|
||
}
|
||
|
||
interfaces = append(interfaces, iface)
|
||
}
|
||
|
||
return interfaces
|
||
}
|