Files
membank/auto-check/pkg/discovery/scanner.go
张威33321 906bb54aaa 重构 auto-check:状态数据下沉各包,workflow 精简为纯调度
- discovery: ping 探测存活 + ARP 解析 MAC,包级 Devices map,串行扫描
- stress: 脚本生成模式(BuildScript/ParseResults),ToolSet 工具检测,包级 Results map
- report: 包级 Printed map,SaveAndPrintDeviceReport 保存+打印
- sshclient: 包级 RunCommand
- workflow: 仅持有 config,Start() 固定循环,直接调用各包方法
- config: 移除 ScanConfig.Concurrency(串行扫描无需并发数)
2026-08-12 17:11:59 +08:00

107 lines
2.4 KiB
Go
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.
package discovery
import (
"fmt"
"net"
"os/exec"
"runtime"
"time"
"auto-check/pkg/model"
)
// Scanner 网段扫描器(串行,按顺序逐个探测)
type Scanner struct {
CIDR string
Timeout time.Duration
}
// NewScanner 创建扫描器
func NewScanner(cidr string, timeout time.Duration) *Scanner {
return &Scanner{
CIDR: cidr,
Timeout: timeout,
}
}
// Scan 扫描网段,返回存活设备列表(含 MAC 地址)
// 串行逐个探测,每个 IP 有超时保护
func (s *Scanner) Scan() []model.Device {
ips, ok := s.candidateIPs()
if !ok {
return nil
}
fmt.Printf("[扫描] 网段 %s共 %d 个IP开始探测...\n", s.CIDR, len(ips))
var results []model.Device
for _, ip := range ips {
if dev, ok := s.probe(ip); ok {
results = append(results, dev)
}
}
fmt.Printf("[扫描] 完成,发现 %d 台存活设备\n", len(results))
return results
}
// candidateIPs 解析网段并生成候选 IP 列表(排除网络地址和广播地址)
func (s *Scanner) candidateIPs() ([]net.IP, bool) {
ip, ipnet, err := net.ParseCIDR(s.CIDR)
if err != nil {
fmt.Printf("[扫描] 网段解析失败: %v\n", err)
return nil, false
}
var ips []net.IP
for ip := ip.Mask(ipnet.Mask); ipnet.Contains(ip); inc(ip) {
dst := make(net.IP, len(ip))
copy(dst, ip)
ips = append(ips, dst)
}
if len(ips) > 2 {
ips = ips[1 : len(ips)-1]
}
return ips, true
}
// probe 探测单个 IP存活则返回设备信息MAC 通过 ARP 表查询)
func (s *Scanner) probe(ip net.IP) (model.Device, bool) {
if !s.isAlive(ip) {
return model.Device{}, false
}
mac := lookupMAC(ip.String())
desc := "无MAC"
if mac != "" {
desc = mac
}
fmt.Printf(" [+] %s 存活 (MAC: %s)\n", ip, desc)
return model.Device{IP: ip.String(), MAC: mac}, true
}
// isAlive 用 ping 探测单个 IP 是否存活(内置超时保护)
func (s *Scanner) isAlive(ip net.IP) bool {
waitMs := s.Timeout.Milliseconds()
if waitMs < 1000 {
waitMs = 1000
}
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
}
// inc IP 递增
func inc(ip net.IP) {
for j := len(ip) - 1; j >= 0; j-- {
ip[j]++
if ip[j] > 0 {
break
}
}
}