Merge branch 'master' of http://gitea.stonelan.cn/admin/membank
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
# auto-check
|
# auto-check
|
||||||
|
|
||||||
自动化网段扫描 + SSH 登录 + 远程压力测试工具。
|
自动化目标扫描 + SSH 登录 + 远程压力测试工具(支持 CIDR 和 IP 范围格式)。
|
||||||
|
|
||||||
基于 [cobra](https://github.com/spf13/cobra) 命令行框架。
|
基于 [cobra](https://github.com/spf13/cobra) 命令行框架。
|
||||||
|
|
||||||
@@ -9,7 +9,7 @@
|
|||||||
| 子命令 | 功能 | 包 |
|
| 子命令 | 功能 | 包 |
|
||||||
|--------|------|-----|
|
|--------|------|-----|
|
||||||
| `run` | 完整流程:发现 → SSH → 压测 | 全部 |
|
| `run` | 完整流程:发现 → SSH → 压测 | 全部 |
|
||||||
| `scan` | 仅扫描网段,发现存活设备 | `pkg/discovery` |
|
| `scan` | 仅扫描目标,发现存活设备 | `pkg/discovery` |
|
||||||
| `stress` | 对指定 IP 执行压力测试 | `pkg/stress` + `pkg/sshclient` |
|
| `stress` | 对指定 IP 执行压力测试 | `pkg/stress` + `pkg/sshclient` |
|
||||||
|
|
||||||
## 安装
|
## 安装
|
||||||
@@ -24,9 +24,12 @@ go build -o auto-check .
|
|||||||
# 查看帮助
|
# 查看帮助
|
||||||
./auto-check --help
|
./auto-check --help
|
||||||
|
|
||||||
# 仅扫描网段
|
# 仅扫描目标(CIDR 格式)
|
||||||
./auto-check scan --cidr 192.168.1.0/24
|
./auto-check scan --cidr 192.168.1.0/24
|
||||||
|
|
||||||
|
# 仅扫描目标(IP 范围格式)
|
||||||
|
./auto-check scan --cidr 192.168.1.1-192.168.1.100
|
||||||
|
|
||||||
# 对指定主机执行压力测试
|
# 对指定主机执行压力测试
|
||||||
./auto-check stress --ips 192.168.1.100,192.168.1.101 --user root --password secret --stress cpu,memory,disk
|
./auto-check stress --ips 192.168.1.100,192.168.1.101 --user root --password secret --stress cpu,memory,disk
|
||||||
|
|
||||||
@@ -38,7 +41,7 @@ go build -o auto-check .
|
|||||||
|
|
||||||
| 标志 | 默认值 | 说明 |
|
| 标志 | 默认值 | 说明 |
|
||||||
|------|--------|------|
|
|------|--------|------|
|
||||||
| `--cidr` | `192.168.1.0/24` | 目标网段 (CIDR) |
|
| `--cidr` | `192.168.1.0/24` | 目标网段或 IP 范围 (CIDR 或 起始IP-结束IP) |
|
||||||
| `--user` | `root` | SSH 用户名 |
|
| `--user` | `root` | SSH 用户名 |
|
||||||
| `--password` | _(空)_ | SSH 密码 |
|
| `--password` | _(空)_ | SSH 密码 |
|
||||||
| `--key` | _(空)_ | SSH 私钥路径 |
|
| `--key` | _(空)_ | SSH 私钥路径 |
|
||||||
|
|||||||
@@ -2,14 +2,17 @@
|
|||||||
# 所有参数仅从本文件加载,按分类组织
|
# 所有参数仅从本文件加载,按分类组织
|
||||||
|
|
||||||
# --- 网段扫描 ---
|
# --- 网段扫描 ---
|
||||||
|
# 支持两种格式:
|
||||||
|
# - CIDR: "10.0.3.0/24"
|
||||||
|
# - IP 范围: "10.0.3.1-10.0.3.100"
|
||||||
scan:
|
scan:
|
||||||
cidr: "10.0.3.0/24"
|
cidr: "10.107.95.2-10.107.95.2"
|
||||||
timeout: 3s
|
timeout: 3s
|
||||||
concurrency: 10
|
concurrency: 10
|
||||||
|
|
||||||
# --- SSH 认证 ---
|
# --- SSH 认证 ---
|
||||||
ssh:
|
ssh:
|
||||||
user: "admin"
|
user: "admin-pc"
|
||||||
password: "admin123"
|
password: "admin123"
|
||||||
key: ""
|
key: ""
|
||||||
port: 22
|
port: 22
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ var rootCmd = &cobra.Command{
|
|||||||
Use: "auto-check",
|
Use: "auto-check",
|
||||||
Short: "自动化设备发现 + SSH 登录 + 远程压力测试工具",
|
Short: "自动化设备发现 + SSH 登录 + 远程压力测试工具",
|
||||||
Long: `auto-check 是一个自动化运维工具,支持:
|
Long: `auto-check 是一个自动化运维工具,支持:
|
||||||
1. 网段扫描发现存活设备
|
1. 目标扫描发现存活设备(支持 CIDR 和 IP 范围格式)
|
||||||
2. 自动 SSH 登录验证
|
2. 自动 SSH 登录验证
|
||||||
3. 远程执行压力测试(CPU/内存/磁盘/网络)
|
3. 远程执行压力测试(CPU/内存/磁盘/网络)
|
||||||
|
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ var runCmd = &cobra.Command{
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
fmt.Printf(" [配置] 加载完成: 网段=%s 间隔=%v 压测=%s\n",
|
fmt.Printf(" [配置] 加载完成: 目标=%s 间隔=%v 压测=%s\n",
|
||||||
cfg.Scan.CIDR, cfg.Workflow.Interval, cfg.Stress.Types)
|
cfg.Scan.CIDR, cfg.Workflow.Interval, cfg.Stress.Types)
|
||||||
|
|
||||||
// 启动工作流(永久循环)
|
// 启动工作流(永久循环)
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ type Config struct {
|
|||||||
// 分类配置项
|
// 分类配置项
|
||||||
// ============================
|
// ============================
|
||||||
|
|
||||||
// ScanConfig 网段扫描
|
// ScanConfig 目标扫描配置(支持 CIDR 和 IP 范围格式)
|
||||||
type ScanConfig struct {
|
type ScanConfig struct {
|
||||||
CIDR string `yaml:"cidr"`
|
CIDR string `yaml:"cidr"`
|
||||||
Timeout time.Duration `yaml:"timeout"`
|
Timeout time.Duration `yaml:"timeout"`
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ import (
|
|||||||
"golang.org/x/text/transform"
|
"golang.org/x/text/transform"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Scanner 网段扫描器(并发 ping 探测)
|
// Scanner 网段扫描器(并发 ping 探测,支持 CIDR 和 IP 范围格式)
|
||||||
type Scanner struct {
|
type Scanner struct {
|
||||||
CIDR string
|
CIDR string
|
||||||
Timeout time.Duration // 单 IP 探测超时
|
Timeout time.Duration // 单 IP 探测超时
|
||||||
@@ -40,7 +40,7 @@ func (s *Scanner) Scan() []model.Device {
|
|||||||
if !ok {
|
if !ok {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
fmt.Printf("[扫描] 网段 %s,共 %d 个IP,%d 并发 ping 探测...\n", s.CIDR, len(ips), s.Concurrency)
|
fmt.Printf("[扫描] 目标 %s,共 %d 个IP,%d 并发 ping 探测...\n", s.CIDR, len(ips), s.Concurrency)
|
||||||
|
|
||||||
jobs := make(chan string, len(ips))
|
jobs := make(chan string, len(ips))
|
||||||
results := make(chan model.Device, len(ips))
|
results := make(chan model.Device, len(ips))
|
||||||
@@ -75,8 +75,21 @@ func (s *Scanner) Scan() []model.Device {
|
|||||||
return devices
|
return devices
|
||||||
}
|
}
|
||||||
|
|
||||||
// candidateIPs 解析网段并生成候选 IP 列表(排除网络地址和广播地址)
|
// candidateIPs 解析网段并生成候选 IP 列表。
|
||||||
|
// 支持两种格式:
|
||||||
|
// - CIDR: "10.0.3.0/24"(排除网络地址和广播地址)
|
||||||
|
// - IP 范围: "10.0.3.1-10.0.3.100"(包含起始和结束 IP)
|
||||||
func (s *Scanner) candidateIPs() ([]string, bool) {
|
func (s *Scanner) candidateIPs() ([]string, bool) {
|
||||||
|
// 检查是否为 IP 范围格式
|
||||||
|
if strings.Contains(s.CIDR, "-") {
|
||||||
|
return s.parseIPRange()
|
||||||
|
}
|
||||||
|
// 否则按 CIDR 解析
|
||||||
|
return s.parseCIDR()
|
||||||
|
}
|
||||||
|
|
||||||
|
// parseCIDR 解析 CIDR 格式并生成候选 IP 列表
|
||||||
|
func (s *Scanner) parseCIDR() ([]string, bool) {
|
||||||
_, ipnet, err := net.ParseCIDR(s.CIDR)
|
_, ipnet, err := net.ParseCIDR(s.CIDR)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("[扫描] 网段解析失败: %v\n", err)
|
fmt.Printf("[扫描] 网段解析失败: %v\n", err)
|
||||||
@@ -93,6 +106,49 @@ func (s *Scanner) candidateIPs() ([]string, bool) {
|
|||||||
return ips, true
|
return ips, true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// parseIPRange 解析 IP 范围格式(如 "10.0.3.1-10.0.3.100")
|
||||||
|
func (s *Scanner) parseIPRange() ([]string, bool) {
|
||||||
|
parts := strings.SplitN(s.CIDR, "-", 2)
|
||||||
|
if len(parts) != 2 {
|
||||||
|
fmt.Printf("[扫描] IP 范围格式无效: %s\n", s.CIDR)
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
startIP := net.ParseIP(strings.TrimSpace(parts[0]))
|
||||||
|
endIP := net.ParseIP(strings.TrimSpace(parts[1]))
|
||||||
|
if startIP == nil || endIP == nil {
|
||||||
|
fmt.Printf("[扫描] IP 地址解析失败: %s\n", s.CIDR)
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
// 转换为 4 字节 IPv4
|
||||||
|
start := startIP.To4()
|
||||||
|
end := endIP.To4()
|
||||||
|
if start == nil || end == nil {
|
||||||
|
fmt.Printf("[扫描] 仅支持 IPv4 范围: %s\n", s.CIDR)
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
// 确保起始 <= 结束
|
||||||
|
if ipToUint32(start) > ipToUint32(end) {
|
||||||
|
fmt.Printf("[扫描] 起始 IP 大于结束 IP: %s\n", s.CIDR)
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
var ips []string
|
||||||
|
for ip := make(net.IP, len(start)); ; {
|
||||||
|
copy(ip, start)
|
||||||
|
ips = append(ips, ip.String())
|
||||||
|
if start.Equal(end) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
inc(start)
|
||||||
|
}
|
||||||
|
return ips, true
|
||||||
|
}
|
||||||
|
|
||||||
|
// ipToUint32 将 IPv4 地址转换为 uint32 用于比较
|
||||||
|
func ipToUint32(ip net.IP) uint32 {
|
||||||
|
ip = ip.To4()
|
||||||
|
return uint32(ip[0])<<24 | uint32(ip[1])<<16 | uint32(ip[2])<<8 | uint32(ip[3])
|
||||||
|
}
|
||||||
|
|
||||||
// ping 探测单个 IP 是否存活(ICMP,经系统 ping 命令)。
|
// ping 探测单个 IP 是否存活(ICMP,经系统 ping 命令)。
|
||||||
// 仅凭 exit code 不可靠(Windows 在某些代答/虚拟网卡场景会返回 0),
|
// 仅凭 exit code 不可靠(Windows 在某些代答/虚拟网卡场景会返回 0),
|
||||||
// 因此解析输出,要求至少收到 1 个回包。
|
// 因此解析输出,要求至少收到 1 个回包。
|
||||||
|
|||||||
@@ -166,7 +166,7 @@ func (r *Report) ToText() string {
|
|||||||
|
|
||||||
// 配置摘要
|
// 配置摘要
|
||||||
sb.WriteString("── 配置摘要 ──\n")
|
sb.WriteString("── 配置摘要 ──\n")
|
||||||
sb.WriteString(fmt.Sprintf(" 网段: %s\n", r.Config.CIDR))
|
sb.WriteString(fmt.Sprintf(" 目标: %s\n", r.Config.CIDR))
|
||||||
sb.WriteString(fmt.Sprintf(" SSH端口: %d\n", r.Config.Port))
|
sb.WriteString(fmt.Sprintf(" SSH端口: %d\n", r.Config.Port))
|
||||||
sb.WriteString(fmt.Sprintf(" SSH用户: %s\n", r.Config.User))
|
sb.WriteString(fmt.Sprintf(" SSH用户: %s\n", r.Config.User))
|
||||||
sb.WriteString(fmt.Sprintf(" 并发数: %d\n", r.Config.Concurrency))
|
sb.WriteString(fmt.Sprintf(" 并发数: %d\n", r.Config.Concurrency))
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
总耗时: {{ .Duration }}
|
总耗时: {{ .Duration }}
|
||||||
{{ "" }}
|
{{ "" }}
|
||||||
── 配置 ──
|
── 配置 ──
|
||||||
网段: {{ .Config.CIDR }}
|
目标: {{ .Config.CIDR }}
|
||||||
SSH: {{ .Config.User }}@:{{ .Config.Port }}
|
SSH: {{ .Config.User }}@:{{ .Config.Port }}
|
||||||
压测: {{ .Config.StressTypes }}
|
压测: {{ .Config.StressTypes }}
|
||||||
并发: {{ .Config.Concurrency }}
|
并发: {{ .Config.Concurrency }}
|
||||||
|
|||||||
Reference in New Issue
Block a user