Update auto-check config and stress modules
This commit is contained in:
@@ -79,11 +79,12 @@ func BuildMetrics(types []TestType, tools ToolSet) []Metric {
|
||||
type Config struct {
|
||||
Duration time.Duration
|
||||
Threads int
|
||||
MemSizeMB int // 0=自动(可用60%)
|
||||
DiskSizeMB int // 0=默认1024
|
||||
DiskDir string // 空=自动临时目录
|
||||
TempLogInt time.Duration // 0=10s
|
||||
TempLimit float64 // 温度上限(°C),0=不判定
|
||||
MemSizeMB int // 0=自动(可用60%)
|
||||
DiskSizeMB int // 0=默认1024
|
||||
DiskDir string // 空=自动临时目录
|
||||
TempLogInt time.Duration
|
||||
TempLimit float64 // 温度上限(°C),0=不判定
|
||||
UseMirror bool // 在线安装时切换国内镜像源(清华TUNA)
|
||||
}
|
||||
|
||||
// DefaultConfig 默认配置
|
||||
|
||||
@@ -36,7 +36,7 @@ type Runner struct {
|
||||
// NewRunner 创建执行器(检查/在线安装 → 构建指标 → 生成脚本 → 执行)
|
||||
func NewRunner(cfg Config, types []TestType, client *ssh.Client, autoInstall bool, sudoPwd string) *Runner {
|
||||
// 1. 检测工具,缺失时按发行版在线安装(可配置国内镜像源加速)
|
||||
tools, failed := EnsureTools(client, requiredTools, autoInstall, sudoPwd)
|
||||
tools, failed := EnsureTools(client, requiredTools, autoInstall, sudoPwd, cfg.UseMirror)
|
||||
metrics := BuildMetrics(types, tools)
|
||||
return &Runner{cfg: cfg, types: types, client: client, tools: tools, metrics: metrics, installFailed: failed}
|
||||
}
|
||||
@@ -285,14 +285,14 @@ func (r *Runner) assembleScript() string {
|
||||
sb.WriteString("set -e\n\n")
|
||||
|
||||
// 导出参数变量
|
||||
sb.WriteString(fmt.Sprintf("export AUTOCHECK_DURATION=%d\n", int(r.cfg.Duration.Seconds())))
|
||||
sb.WriteString(fmt.Sprintf("export AUTOCHECK_THREADS=%d\n", r.cfg.Threads))
|
||||
sb.WriteString(fmt.Sprintf("export AUTOCHECK_DISK_SIZE_MB=%d\n", r.cfg.DiskSizeMB))
|
||||
sb.WriteString(fmt.Sprintf("export AUTOCHECK_MEM_SIZE_MB=%d\n", r.cfg.MemSizeMB))
|
||||
sb.WriteString(fmt.Sprintf("export AUTOCHECK_TEMP_INTERVAL=%d\n", int(r.cfg.TempLogInt.Seconds())))
|
||||
fmt.Fprintf(&sb, "export AUTOCHECK_DURATION=%d\n", int(r.cfg.Duration.Seconds()))
|
||||
fmt.Fprintf(&sb, "export AUTOCHECK_THREADS=%d\n", r.cfg.Threads)
|
||||
fmt.Fprintf(&sb, "export AUTOCHECK_DISK_SIZE_MB=%d\n", r.cfg.DiskSizeMB)
|
||||
fmt.Fprintf(&sb, "export AUTOCHECK_MEM_SIZE_MB=%d\n", r.cfg.MemSizeMB)
|
||||
fmt.Fprintf(&sb, "export AUTOCHECK_TEMP_INTERVAL=%d\n", int(r.cfg.TempLogInt.Seconds()))
|
||||
sb.WriteString("export AUTOCHECK_SAMPLE_INTERVAL=2\n")
|
||||
if r.cfg.DiskDir != "" {
|
||||
sb.WriteString(fmt.Sprintf("export AUTOCHECK_DISK_DIR=%s\n", r.cfg.DiskDir))
|
||||
fmt.Fprintf(&sb, "export AUTOCHECK_DISK_DIR=%s\n", r.cfg.DiskDir)
|
||||
}
|
||||
sb.WriteString("\n")
|
||||
|
||||
@@ -327,17 +327,17 @@ func (r *Runner) assembleScript() string {
|
||||
}
|
||||
if !m.Enabled {
|
||||
// 缺少依赖时仍输出一个 skip 结果,让报告完整展示原因
|
||||
sb.WriteString(fmt.Sprintf("echo '===TEST:%s==='\n", m.Name))
|
||||
fmt.Fprintf(&sb, "echo '===TEST:%s==='\n", m.Name)
|
||||
sb.WriteString("echo 'status:skip'\n")
|
||||
sb.WriteString(fmt.Sprintf("echo 'output:%s'\n", m.DisableReason))
|
||||
fmt.Fprintf(&sb, "echo 'output:%s'\n", m.DisableReason)
|
||||
sb.WriteString("echo ''\n")
|
||||
continue
|
||||
}
|
||||
data := r.readScript(m.Name)
|
||||
if data == nil {
|
||||
sb.WriteString(fmt.Sprintf("echo '===TEST:%s==='\n", m.Name))
|
||||
fmt.Fprintf(&sb, "echo '===TEST:%s==='\n", m.Name)
|
||||
sb.WriteString("echo 'status:skip'\n")
|
||||
sb.WriteString(fmt.Sprintf("echo 'output:脚本文件 scripts/%s.sh 不存在'\n", m.Name))
|
||||
fmt.Fprintf(&sb, "echo 'output:脚本文件 scripts/%s.sh 不存在'\n", m.Name)
|
||||
sb.WriteString("echo ''\n")
|
||||
continue
|
||||
}
|
||||
@@ -406,9 +406,6 @@ func TestDevice(ip string, cfg config.Config) *Report {
|
||||
// "Could not chdir to home directory" 横幅污染命令输出,先建好 HOME
|
||||
sshclient.EnsureHome(conn)
|
||||
|
||||
// 根据配置决定是否在线安装时使用国内镜像源(默认 false,先试系统自带源)
|
||||
SetMirror(cfg.Stress.UseMirror)
|
||||
|
||||
// sudo 密码:优先用专属 sudo_password;为空时退回 SSH 登录密码(飞牛 admin 同密码)
|
||||
sudoPwd := cfg.SSH.SudoPwd
|
||||
if sudoPwd == "" {
|
||||
@@ -424,13 +421,17 @@ func TestDevice(ip string, cfg config.Config) *Report {
|
||||
fmt.Printf(" [MAC] %s -> %s\n", ip, mac)
|
||||
}
|
||||
|
||||
stressCfg := Config{
|
||||
Duration: cfg.Stress.Duration,
|
||||
Threads: cfg.Stress.Threads,
|
||||
DiskSizeMB: 1024,
|
||||
TempLogInt: 10 * time.Second,
|
||||
TempLimit: cfg.Stress.TempLimit,
|
||||
}
|
||||
// 由默认配置 + yaml 映射构造(避免硬编码,便于后续扩展字段)
|
||||
stressCfg := DefaultConfig()
|
||||
stressCfg.Duration = cfg.Stress.Duration
|
||||
stressCfg.Threads = cfg.Stress.Threads
|
||||
stressCfg.MemSizeMB = cfg.Stress.MemSizeMB
|
||||
stressCfg.DiskSizeMB = cfg.Stress.DiskSizeMB
|
||||
stressCfg.DiskDir = cfg.Stress.DiskDir
|
||||
stressCfg.TempLogInt = cfg.Stress.TempInterval
|
||||
stressCfg.TempLimit = cfg.Stress.TempLimit
|
||||
stressCfg.UseMirror = cfg.Stress.UseMirror
|
||||
|
||||
return NewRunner(stressCfg, ParseTypes(cfg.Stress.Types), conn, cfg.Stress.AutoInstall, sudoPwd).Run(ip)
|
||||
}
|
||||
|
||||
|
||||
@@ -13,24 +13,13 @@ import (
|
||||
// 国内镜像源
|
||||
// ============================
|
||||
|
||||
// useMirror 控制是否把远端包管理器切到国内镜像。默认关闭——先用系统自带源
|
||||
// 试装(飞牛/群晖等定制系统常常已预置可用源),失败或超时再开启清华镜像。
|
||||
var useMirror = false
|
||||
|
||||
// SetMirror 设置是否使用国内镜像源(由配置注入)
|
||||
func SetMirror(on bool) {
|
||||
useMirror = on
|
||||
}
|
||||
|
||||
// mirrorName 根据发行版返回镜像别名(用于日志)
|
||||
const mirrorLabel = "清华 TUNA 镜像"
|
||||
|
||||
// setupMirror 在安装前把对应包管理器的源切换为国内镜像(仅 apt 系需要改文件,
|
||||
// 其它包管理器通过参数/变量临时指向镜像)。失败不致命,仅打印警告并继续用原源。
|
||||
func setupMirror(client *ssh.Client, pm string, sudoPwd string) {
|
||||
// setupMirror 在安装前把对应包管理器的源切换为国内镜像(清华 TUNA)。
|
||||
// useMirror=false 时直接跳过(先用系统自带源试装)。失败不致命,仅提示并继续用原源。
|
||||
func setupMirror(client *ssh.Client, pm string, sudoPwd string, useMirror bool) {
|
||||
if !useMirror {
|
||||
return
|
||||
}
|
||||
const label = "清华 TUNA 镜像"
|
||||
switch pm {
|
||||
case "apt-get":
|
||||
// 备份并替换为清华镜像(Debian/Ubuntu 通用,按 lsb_release 选版本)
|
||||
@@ -63,17 +52,14 @@ echo OK`
|
||||
if err != nil || !strings.Contains(out, "OK") {
|
||||
fmt.Printf(" [镜像] apt 切换国内源失败,将使用官方源: %v\n", err)
|
||||
} else {
|
||||
fmt.Printf(" [镜像] apt 已切换至%s\n", mirrorLabel)
|
||||
fmt.Printf(" [镜像] apt 已切换至%s\n", label)
|
||||
}
|
||||
case "dnf", "yum":
|
||||
// 清华镜像站对 dnf/yum 提供 repo 文件;这里用变量临时指向(持久化需改 repo)
|
||||
cmd := `echo "腾讯/清华镜像需手动配置 repo;尝试临时使用 mirrors.tuna.tsinghua.edu.cn 变量"`
|
||||
runPrivileged(client, cmd, sudoPwd)
|
||||
// 通过 baseurl 变量临时覆盖(仅对部分仓库有效,作为加速兜底)
|
||||
fmt.Printf(" [镜像] %s 使用系统默认源(建议手动配置%s repo)\n", pm, mirrorLabel)
|
||||
case "apk":
|
||||
runPrivileged(client, "sed -i 's#https\\?://[^/]*alpinelinux.org#https://mirrors.tuna.tsinghua.edu.cn/alpine#g' /etc/apk/repositories", sudoPwd)
|
||||
fmt.Printf(" [镜像] apk 已切换至%s\n", mirrorLabel)
|
||||
fmt.Printf(" [镜像] apk 已切换至%s\n", label)
|
||||
default:
|
||||
// dnf/yum 等无通用一键切源命令,需手动配置 repo 文件,这里仅提示
|
||||
fmt.Printf(" [镜像] %s 无内置切源逻辑,建议使用系统默认源或手动配置%s repo\n", pm, label)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -81,8 +67,9 @@ echo OK`
|
||||
// 远程工具检测
|
||||
// ============================
|
||||
|
||||
// 压测核心依赖工具(缺则按需在线安装)。lm-sensors 依赖较多,仅单文件
|
||||
// 二进制 stress-ng 与 fio 为必需;sensors 缺失仅影响温度曲线,不阻断压测。
|
||||
// requiredTools 压测核心依赖工具(缺则按需在线安装)。lm-sensors 依赖较多,
|
||||
// 仅单文件二进制 stress-ng 与 fio 为必需;sensors 缺失仅影响温度曲线,不阻断压测。
|
||||
// 这是工具检测的唯一来源,DetectTools/EnsureTools 都从这里取列表,避免两处不一致。
|
||||
var requiredTools = []string{"stress-ng", "fio"}
|
||||
|
||||
// ToolInfo 远程工具信息
|
||||
@@ -112,7 +99,7 @@ func (ts ToolSet) Get(name string) (ToolInfo, bool) {
|
||||
// DetectTools 检测远程所有相关工具是否可用
|
||||
func DetectTools(client *ssh.Client) ToolSet {
|
||||
ts := ToolSet{Tools: make(map[string]ToolInfo)}
|
||||
for _, name := range []string{"stress-ng", "stressapptest", "iperf3", "fio", "lm-sensors"} {
|
||||
for _, name := range requiredTools {
|
||||
if info, ok := detectOne(client, name); ok {
|
||||
ts.Tools[name] = info
|
||||
}
|
||||
@@ -121,9 +108,10 @@ func DetectTools(client *ssh.Client) ToolSet {
|
||||
}
|
||||
|
||||
// EnsureTools 检测工具;缺失且 autoInstall=true 时按发行版自动安装。
|
||||
// sudoPwd 为非 root 用户执行安装时提供(为空则尝试免密 sudo)。
|
||||
// 返回安装后的工具集合,以及最终仍缺失的工具名列表。
|
||||
func EnsureTools(client *ssh.Client, names []string, autoInstall bool, sudoPwd string) (ToolSet, []string) {
|
||||
// sudoPwd 为非 root 用户执行安装时提供(为空则尝试免密 sudo)。useMirror=true
|
||||
// 时安装前把包管理器源切换为国内镜像(清华 TUNA)。返回安装后的工具集合,
|
||||
// 以及最终仍缺失的工具名列表。
|
||||
func EnsureTools(client *ssh.Client, names []string, autoInstall bool, sudoPwd string, useMirror bool) (ToolSet, []string) {
|
||||
ts := DetectTools(client)
|
||||
var missing []string
|
||||
for _, n := range names {
|
||||
@@ -142,7 +130,7 @@ func EnsureTools(client *ssh.Client, names []string, autoInstall bool, sudoPwd s
|
||||
return ts, missing // 无法识别包管理器,跳过安装
|
||||
}
|
||||
// 安装前先把源切到国内镜像(使用官方源在网络差的环境会超时)
|
||||
setupMirror(client, pm, sudoPwd)
|
||||
setupMirror(client, pm, sudoPwd, useMirror)
|
||||
// 仅 apt 系需要先刷新元数据
|
||||
if pm == "apt-get" {
|
||||
if out, err := runPrivileged(client, "timeout 180 apt-get update 2>&1", sudoPwd); err != nil || strings.Contains(out, "Err") || strings.Contains(out, "Failed") {
|
||||
@@ -282,24 +270,13 @@ func detectOne(client *ssh.Client, name string) (ToolInfo, bool) {
|
||||
return ToolInfo{}, false
|
||||
}
|
||||
|
||||
var version string
|
||||
switch name {
|
||||
case "stress-ng":
|
||||
v, _ := sshclient.RunCommand(client, path+" --version 2>&1 | head -1")
|
||||
version = strings.TrimSpace(v)
|
||||
case "stressapptest":
|
||||
v, _ := sshclient.RunCommand(client, path+" --help 2>&1 | head -1")
|
||||
version = strings.TrimSpace(v)
|
||||
case "iperf3":
|
||||
v, _ := sshclient.RunCommand(client, path+" --version 2>&1 | head -1")
|
||||
version = strings.TrimSpace(v)
|
||||
case "fio":
|
||||
v, _ := sshclient.RunCommand(client, path+" --version 2>&1 | head -1")
|
||||
version = strings.TrimSpace(v)
|
||||
case "lm-sensors":
|
||||
v, _ := sshclient.RunCommand(client, path+" -v 2>&1 | head -1")
|
||||
version = strings.TrimSpace(v)
|
||||
// 取版本:lm-sensors 仅支持 -v,其余工具均支持 --version
|
||||
verFlag := "--version"
|
||||
if name == "lm-sensors" {
|
||||
verFlag = "-v"
|
||||
}
|
||||
v, _ := sshclient.RunCommand(client, path+" "+verFlag+" 2>&1 | head -1")
|
||||
version := strings.TrimSpace(v)
|
||||
|
||||
return ToolInfo{Name: name, Path: path, Version: version}, true
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user