新增 auto-check 工具:网段扫描+SSH登录+压力测试永久循环工作流
- pkg/discovery: TCP端口探测存活主机,ARP表解析MAC作为设备唯一标识 - pkg/sshclient: SSH连接(密码/密钥认证)与远程命令执行 - pkg/stress: stress-ng/stressapptest 压测(cpu/memory/disk/memnative/full)+温度与dmesg监控 - pkg/report: 检测报告生成(文本/JSON) - pkg/workflow: 永久循环工作流(间隔可配),MAC唯一标识设备,增量测试+状态变化打印 - pkg/config: YAML分类配置(scan/ssh/stress/report/workflow) - cmd: cobra入口,仅 --config 指定配置文件
This commit is contained in:
93
auto-check/pkg/sshclient/sshclient.go
Normal file
93
auto-check/pkg/sshclient/sshclient.go
Normal file
@@ -0,0 +1,93 @@
|
||||
package sshclient
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"golang.org/x/crypto/ssh"
|
||||
)
|
||||
|
||||
// Client SSH 客户端封装
|
||||
type Client struct {
|
||||
User string
|
||||
Password string
|
||||
KeyFile string
|
||||
Port int
|
||||
Timeout time.Duration
|
||||
}
|
||||
|
||||
// NewClient 创建 SSH 客户端
|
||||
func NewClient(user, password, keyFile string, port int, timeout time.Duration) *Client {
|
||||
return &Client{
|
||||
User: user,
|
||||
Password: password,
|
||||
KeyFile: keyFile,
|
||||
Port: port,
|
||||
Timeout: timeout,
|
||||
}
|
||||
}
|
||||
|
||||
// Connect 尝试 SSH 连接,返回 SSH client
|
||||
func (c *Client) Connect(ip string) (*ssh.Client, error) {
|
||||
config, err := c.buildConfig()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("SSH 配置构建失败: %w", err)
|
||||
}
|
||||
|
||||
addr := fmt.Sprintf("%s:%d", ip, c.Port)
|
||||
client, err := ssh.Dial("tcp", addr, config)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("SSH 连接 %s 失败: %w", addr, err)
|
||||
}
|
||||
return client, nil
|
||||
}
|
||||
|
||||
// RunCommand 在远程主机执行命令,返回输出
|
||||
func (c *Client) RunCommand(client *ssh.Client, command string) (string, error) {
|
||||
session, err := client.NewSession()
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("创建会话失败: %w", err)
|
||||
}
|
||||
defer session.Close()
|
||||
|
||||
out, err := session.CombinedOutput(command)
|
||||
if err != nil {
|
||||
return string(out), fmt.Errorf("命令执行失败: %w, 输出: %s", err, string(out))
|
||||
}
|
||||
return string(out), nil
|
||||
}
|
||||
|
||||
// buildConfig 构建 SSH 认证配置
|
||||
func (c *Client) buildConfig() (*ssh.ClientConfig, error) {
|
||||
var authMethods []ssh.AuthMethod
|
||||
|
||||
// 密码认证
|
||||
if c.Password != "" {
|
||||
authMethods = append(authMethods, ssh.Password(c.Password))
|
||||
}
|
||||
|
||||
// 密钥认证
|
||||
if c.KeyFile != "" {
|
||||
key, err := os.ReadFile(c.KeyFile)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("读取密钥文件失败: %w", err)
|
||||
}
|
||||
signer, err := ssh.ParsePrivateKey(key)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("解析私钥失败: %w", err)
|
||||
}
|
||||
authMethods = append(authMethods, ssh.PublicKeys(signer))
|
||||
}
|
||||
|
||||
if len(authMethods) == 0 {
|
||||
return nil, fmt.Errorf("未提供认证方式(密码或密钥)")
|
||||
}
|
||||
|
||||
return &ssh.ClientConfig{
|
||||
User: c.User,
|
||||
Auth: authMethods,
|
||||
HostKeyCallback: ssh.InsecureIgnoreHostKey(),
|
||||
Timeout: c.Timeout,
|
||||
}, nil
|
||||
}
|
||||
Reference in New Issue
Block a user