重构 auto-check:拆分包架构,精简 workflow 为纯调度循环

各包职责:
- config: 分类 YAML 配置
- model: Device/IP/MAC 公共类型
- discovery: 扫描 + ARP MAC 解析 + Devices 变量
- sshclient: SSH 连接
- stress: stress-ng/stressapptest 压测 + Results 变量
- report: 80mm 热敏模板/sparkline/打印 + Printed 变量
- workflow: 永久循环调度 + Start/Stop

workflow 已精简为 100 行纯编排,所有业务逻辑下沉各包
This commit is contained in:
张威33321
2026-08-11 20:58:19 +08:00
parent 19f6050147
commit 700ba91883
17 changed files with 867 additions and 516 deletions

View File

@@ -9,40 +9,51 @@ import (
"strings"
"sync"
"time"
"auto-check/pkg/model"
)
// Host 存活主机信息
type Host struct {
IP net.IP
MAC string // 物理地址(设备唯一标识)
Alive bool
OpenPort int
}
// Devices 设备表IP → 设备),每轮 Discover() 后更新,包级公开
var Devices = make(map[string]model.Device)
// Scanner 网段扫描器
type Scanner struct {
CIDR string
Port int
Timeout time.Duration
Concurrency int
}
// NewScanner 创建扫描器
func NewScanner(cidr string, port int, timeout time.Duration, concurrency int) *Scanner {
func NewScanner(cidr string, timeout time.Duration, concurrency int) *Scanner {
return &Scanner{
CIDR: cidr,
Port: port,
Timeout: timeout,
Concurrency: concurrency,
}
}
// Scan 扫描网段,返回存活主机列表
func (s *Scanner) Scan() []Host {
// Scan 扫描网段,返回存活设备列表
func (s *Scanner) Scan() []model.Device {
ips, ok := s.candidateIPs()
if !ok {
return nil
}
fmt.Printf("[扫描] 网段 %s共 %d 个IP开始探测...\n", s.CIDR, len(ips))
results := s.probeAll(ips)
fmt.Printf("[扫描] 完成,发现 %d 台存活设备\n", len(results))
return results
}
// candidateIPs 解析网段并生成候选 IP 列表(排除网络地址和广播地址)
// 网段解析失败时返回 false
func (s *Scanner) candidateIPs() ([]net.IP, bool) {
ip, ipnet, err := net.ParseCIDR(s.CIDR)
if err != nil {
fmt.Printf("[扫描] 网段解析失败: %v\n", err)
return nil
return nil, false
}
var ips []net.IP
@@ -55,13 +66,14 @@ func (s *Scanner) Scan() []Host {
if len(ips) > 2 {
ips = ips[1 : len(ips)-1]
}
return ips, true
}
fmt.Printf("[扫描] 网段 %s共 %d 个IP开始探测...\n", s.CIDR, len(ips))
// 并发探测
// probeAll 并发探测所有候选 IP返回存活设备列表
func (s *Scanner) probeAll(ips []net.IP) []model.Device {
var mu sync.Mutex
var wg sync.WaitGroup
var results []Host
var results []model.Device
sem := make(chan struct{}, s.Concurrency)
for _, ip := range ips {
@@ -71,54 +83,54 @@ func (s *Scanner) Scan() []Host {
defer wg.Done()
defer func() { <-sem }()
h := s.probe(target)
if h.Alive {
// 获取 MAC 地址TCP 探测已触发 ARP 解析)
h.MAC = getMAC(target.String())
mu.Lock()
results = append(results, h)
mu.Unlock()
desc := "无MAC"
if h.MAC != "" {
desc = h.MAC
}
fmt.Printf(" [+] %s 存活 (MAC: %s, 端口 %d 开放)\n", target, desc, h.OpenPort)
dev, ok := s.probeDevice(target)
if !ok {
return
}
mu.Lock()
results = append(results, dev)
mu.Unlock()
desc := "无MAC"
if dev.MAC != "" {
desc = dev.MAC
}
fmt.Printf(" [+] %s 存活 (MAC: %s)\n", target, desc)
}(ip)
}
wg.Wait()
fmt.Printf("[扫描] 完成,发现 %d 台存活主机\n", len(results))
return results
}
// probe 探测单个 IP
func (s *Scanner) probe(ip net.IP) Host {
h := Host{IP: ip}
// TCP 端口探测(连接成功会触发本地 ARP 解析)
addr := net.JoinHostPort(ip.String(), fmt.Sprintf("%d", s.Port))
conn, err := net.DialTimeout("tcp", addr, s.Timeout)
if err == nil {
conn.Close()
h.Alive = true
h.OpenPort = s.Port
return h
// probeDevice 探测单个 IP,存活则返回设备信息
func (s *Scanner) probeDevice(ip net.IP) (model.Device, bool) {
if !s.probe(ip) {
return model.Device{}, false
}
// 备选:尝试常见端口
for _, p := range []int{22, 80, 443, 8080, 3306} {
addr = net.JoinHostPort(ip.String(), fmt.Sprintf("%d", p))
conn, err = net.DialTimeout("tcp", addr, s.Timeout)
if err == nil {
conn.Close()
h.Alive = true
h.OpenPort = p
return h
}
// 获取 MAC 地址ping 探测已触发 ARP 解析)
dev := model.Device{
IP: ip.String(),
MAC: getMAC(ip.String()),
}
return dev, true
}
return h
// probe 用 ping 探测单个 IP 是否存活,返回 bool
func (s *Scanner) probe(ip net.IP) bool {
waitMs := s.Timeout.Milliseconds()
if waitMs < 1000 {
waitMs = 1000 // ping 等待至少 1 秒
}
// 各平台 ping 参数不同Linux -W 秒macOS/Windows -W/-w 毫秒
var args []string
switch runtime.GOOS {
case "windows":
args = []string{"-n", "1", "-w", fmt.Sprintf("%d", waitMs), ip.String()}
case "darwin":
args = []string{"-c", "1", "-W", fmt.Sprintf("%d", waitMs), ip.String()}
default:
args = []string{"-c", "1", "-W", fmt.Sprintf("%d", waitMs/1000), ip.String()}
}
return exec.Command("ping", args...).Run() == nil
}
// getMAC 从 ARP 表获取 IP 对应的 MAC 地址(跨平台)
@@ -194,6 +206,19 @@ func macFromUnixArp(ip string) string {
return ""
}
// Discover 扫描并更新包级 Devices map过滤无 MAC 设备)
func (s *Scanner) Discover() {
devices := s.Scan()
Devices = make(map[string]model.Device, len(devices))
for _, dev := range devices {
if dev.MAC == "" {
fmt.Printf(" [!] %s 无 MACARP 未解析),下轮重试\n", dev.IP)
continue
}
Devices[dev.IP] = dev
}
}
// inc IP 递增
func inc(ip net.IP) {
for j := len(ip) - 1; j >= 0; j-- {