Files
membank/auto-check/pkg/stress/tools.go
12600k-rog-d4 b673ed62f9 docker
2026-08-24 00:35:30 +08:00

78 lines
2.8 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 stress
import (
"fmt"
"strings"
"auto-check/pkg/sshclient"
"golang.org/x/crypto/ssh"
)
// ============================
// Docker 环境检测与特权执行(压测统一在容器中执行,工具预装在镜像里)
// ============================
// DockerInfo Docker 运行环境信息
type DockerInfo struct {
Version string // Docker 版本号(如 24.0.7
Available bool // 是否可用
}
// IsDockerAvailable 检测远程 Docker 是否可用(飞牛 NAS 默认已安装)。
// 非 root 用户(如 fnOS admin无 docker.sock 权限,需通过 sudo 执行。
func IsDockerAvailable(client *ssh.Client, sudoPwd string) DockerInfo {
out, err := runPrivileged(client, "docker version --format '{{.Server.Version}}' 2>/dev/null", sudoPwd)
if err != nil || strings.TrimSpace(out) == "" {
return DockerInfo{Available: false}
}
return DockerInfo{
Version: strings.TrimSpace(out),
Available: true,
}
}
// runPrivileged 以特权执行命令root 直接执行;非 root 用 sudo
// 若提供了 sudo 密码则通过 stdin 喂入(无需 NOPASSWD 配置)。
// fnOS 的 admin 用户无 docker.sock 权限docker 命令均需走此路径。
func runPrivileged(client *ssh.Client, cmd, sudoPwd string) (string, error) {
// 已是 root 则直接执行
if out, err := sshclient.RunCommand(client, "id -u"); err == nil && strings.TrimSpace(out) == "0" {
return sshclient.RunCommand(client, cmd)
}
// 非 root尝试 sudo
if sudoPwd != "" {
// echo 密码 | sudo -S 执行;整条命令用双引号包裹,避免命令内部单引号嵌套冲突。
// 仅对命令内的双引号转义docker 命令均不含双引号,安全)。
quoted := strings.ReplaceAll(singleLine(cmd), `"`, `\"`)
wrapped := fmt.Sprintf("echo %s | sudo -S -- sh -c \"%s\"", shellQuote(sudoPwd), quoted)
return sshclient.RunCommand(client, wrapped)
}
// 无密码:先尝试免密 sudo (-n),失败则回退普通 sudo会提示需要密码
quoted := strings.ReplaceAll(singleLine(cmd), `"`, `\"`)
if out, err := sshclient.RunCommand(client, "sudo -n -- sh -c \""+quoted+"\""); err == nil {
return out, nil
}
return sshclient.RunCommand(client, "sudo -- sh -c \""+quoted+"\"")
}
// shellQuote 转义单引号,避免密码破坏命令结构
func shellQuote(s string) string {
return "'" + strings.ReplaceAll(s, "'", `'\''`) + "'"
}
// singleLine 去掉换行,保证能塞进 sh -c '...'
func singleLine(s string) string {
return strings.ReplaceAll(strings.ReplaceAll(s, "\n", " "), "\r", "")
}
// truncate 截断过长的输出,便于日志展示
func truncate(s string, n int) string {
// 去掉 ANSI/多余空行,只保留前 n 个字符
s = strings.TrimSpace(s)
if len([]rune(s)) > n {
return string([]rune(s)[:n]) + "...(truncated)"
}
return s
}