package cmd import ( "os" "time" "github.com/evil7/hostsync/config" "github.com/evil7/hostsync/core" "github.com/evil7/hostsync/utils" "github.com/spf13/cobra" ) // serverCmd 服务器管理命令 var serverCmd = &cobra.Command{ Use: "server [command]", Short: "管理预设 DNS 服务器", Long: `管理预设DNS服务器配置,支持列出、测试服务器。 子命令: list 列出所有预设服务器 test 测试所有服务器响应 test 测试指定服务器 示例: hostsync server # 列出所有预设服务器(默认) hostsync server list # 列出所有预设服务器 hostsync server test # 测试所有服务器响应 hostsync server test Cloudflare # 测试指定服务器`, Run: runServerDefault, // 添加默认运行函数 } var serverListCmd = &cobra.Command{ Use: "list", Short: "列出所有预设服务器", Run: runServerList, } var serverTestCmd = &cobra.Command{ Use: "test [serverName]", Short: "测试服务器响应时间", Args: cobra.MaximumNArgs(1), Run: runServerTest, } func init() { serverCmd.AddCommand(serverListCmd) serverCmd.AddCommand(serverTestCmd) } // runServerDefault 默认运行server命令时列出所有服务器 func runServerDefault(cmd *cobra.Command, args []string) { runServerList(cmd, args) } func runServerList(cmd *cobra.Command, args []string) { if len(config.DNSServers) == 0 { utils.LogInfo("没有找到预设DNS服务器配置") return } utils.LogResult("🌐 预设DNS服务器列表 (%d 个)\n", len(config.DNSServers)) headers := []string{"名称", "DNS地址", "DoH地址"} var rows [][]string for _, server := range config.DNSServers { dnsAddr := server.DNS if dnsAddr == "" { dnsAddr = "-" } dohAddr := server.DoH if dohAddr == "" { dohAddr = "-" } else { dohAddr = utils.TruncateWithWidth(dohAddr, 50) } rows = append(rows, []string{server.Name, dnsAddr, dohAddr}) } // 设置合适的列宽 columnWidths := []int{15, 20, 50} utils.FormatTable(headers, rows, columnWidths) } func runServerTest(cmd *cobra.Command, args []string) { resolver := core.NewDNSResolver() if len(args) == 0 { // 测试所有服务器 testAllServers(resolver) } else { // 测试指定服务器 serverName := args[0] testServer(resolver, serverName) } } func testAllServers(resolver *core.DNSResolver) { if len(config.DNSServers) == 0 { utils.LogInfo("没有找到预设DNS服务器配置") return } utils.LogInfo("测试所有DNS服务器 (%d 个)", len(config.DNSServers)) // 并发测试结果 type testResult struct { index int name string dnsTime string dohTime string status string } results := make(chan testResult, len(config.DNSServers)) // 并发测试所有服务器 for i, server := range config.DNSServers { go func(idx int, srv config.DNSServer) { dnsTime := "-" dohTime := "-" status := "❌ 不可用" // 测试DNS if srv.DNS != "" { if duration, err := resolver.TestDNSServer(srv.DNS); err == nil { dnsTime = duration.String() status = "✅ 可用" } } // 测试DoH if srv.DoH != "" { if duration, err := resolver.TestDoHServer(srv.DoH); err == nil { dohTime = duration.String() if status != "✅ 可用" { status = "✅ 可用" } } } results <- testResult{ index: idx, name: srv.Name, dnsTime: dnsTime, dohTime: dohTime, status: status, } }(i, server) } // 收集结果并显示进度 headers := []string{"服务器", "DNS响应时间", "DoH响应时间", "状态"} resultMap := make(map[int]testResult) completed := 0 for completed < len(config.DNSServers) { result := <-results resultMap[result.index] = result completed++ utils.LogInfo("已完成测试: %d/%d", completed, len(config.DNSServers)) } // 按原始顺序排序结果 var rows [][]string for i := 0; i < len(config.DNSServers); i++ { result := resultMap[i] rows = append(rows, []string{result.name, result.dnsTime, result.dohTime, result.status}) } // 设置合适的列宽 columnWidths := []int{15, 15, 15, 12} utils.FormatTable(headers, rows, columnWidths) } func testServer(resolver *core.DNSResolver, serverName string) { server := config.GetDNSServer(serverName) if server == nil { utils.LogError("找不到服务器: %s", serverName) utils.LogInfo("使用 'hostsync server list' 查看可用服务器") os.Exit(1) } utils.LogInfo("测试服务器: %s", serverName) // 测试DNS if server.DNS != "" { utils.LogInfo("测试DNS (%s)...", server.DNS) start := time.Now() if duration, err := resolver.TestDNSServer(server.DNS); err != nil { elapsed := time.Since(start) utils.LogError("失败: %v (耗时: %v)", err, elapsed) } else { utils.LogSuccess("成功 (%v)", duration) } } else { utils.LogInfo("DNS: 未配置") } // 测试DoH if server.DoH != "" { utils.LogInfo("测试DoH (%s)...", server.DoH) start := time.Now() if duration, err := resolver.TestDoHServer(server.DoH); err != nil { elapsed := time.Since(start) utils.LogError("失败: %v (耗时: %v)", err, elapsed) } else { utils.LogSuccess("成功 (%v)", duration) } } else { utils.LogInfo("DoH: 未配置") } }