package cmd import ( "agent-wdd/cmd/xray" "agent-wdd/config" "agent-wdd/log" "agent-wdd/op" "agent-wdd/utils" "bytes" "encoding/json" "fmt" "os" "text/template" "github.com/spf13/cobra" ) // 添加proxy子命令 func addProxySubcommands(cmd *cobra.Command) { xrayCmd := &cobra.Command{ Use: "xray", Short: "Xray相关操作", } xrayCmd.AddCommand( &cobra.Command{ Use: "install", Short: "安装Xray", Run: func(cmd *cobra.Command, args []string) { log.Info("Installing Xray...") installXray() }, }, // 其他xray子命令... ) vmessCmd := &cobra.Command{ Use: "vmess [port]", Short: "VMESS代理安装", Run: func(cmd *cobra.Command, args []string) { log.Info("Setting up VMESS proxy...") var port string if len(args) == 0 { log.Info("no port provided, using default port 443") port = "443" } else { port = args[0] } // 执行info all命令 获得归一化的名字 高耦合方案 不推荐 // for _, command := range cmd.Parent().Parent().Commands() { // if command.Name() == "info" { // command.Run(command, []string{"all"}) // } // } // 2. 调用 info all 命令 if err := executeInfoAll(cmd); err != nil { fmt.Printf("Error executing info all: %v\n", err) } installVmess(port) }, } vlessCmd := &cobra.Command{ Use: "vless [port]", Short: "VLESS代理安装", Run: func(cmd *cobra.Command, args []string) { log.Info("Setting up VLESS proxy...") // var port string // if len(args) == 0 { // log.Info("no port provided, using default port 443") // port = "443" // } }, } cmd.AddCommand( xrayCmd, vmessCmd, vlessCmd, // 其他proxy子命令... ) } func executeInfoAll(cmd *cobra.Command) any { // 获取根命令 rootCmd := cmd.Root() // 创建临时上下文 infoCmd, _, err := rootCmd.Find([]string{"info", "all"}) if err != nil { return fmt.Errorf("command not found: %w", err) } // 克隆命令避免污染原始配置 clonedCmd := cloneCommand(infoCmd) // 重置命令状态 clonedCmd.SetArgs([]string{}) clonedCmd.SilenceErrors = true clonedCmd.SilenceUsage = true // 执行命令 return clonedCmd.Execute() } // 深度克隆命令的工具函数 func cloneCommand(cmd *cobra.Command) *cobra.Command { cloned := &cobra.Command{ Use: cmd.Use, Run: cmd.Run, PreRun: cmd.PreRun, PostRun: cmd.PostRun, } cloned.Flags().AddFlagSet(cmd.Flags()) return cloned } // VmessConfig 定义模板数据模型 type VmessConfig struct { PORT string UUID string } type VmessClientConfig struct { ServerNodeName string ServerNodeAddress string VmessConfig } // 安装VMESS代理 最简单快速的模式 func installVmess(port string) (bool, []string) { // 检查是否安装了xray if !op.CommandExistsByPath("xray") { log.Error("Xray is not installed, please install xray first") return false, []string{"Xray is not installed, please install xray first"} } // 构建配置 // 创建新模板并解析 tmpl, err := template.New("vmessConfig").Parse(xray.VmessServerTemplate) if err != nil { return false, []string{err.Error()} } // 准备模板数据 // 执行 xray uuid 拿到返回值 ok, resultLog := op.SingleLineCommandExecutor([]string{"xray", "uuid"}) if !ok { return false, resultLog } if len(resultLog) == 0 { return false, []string{ "xray uuid generate error ! cant not get the uuid", } } uuid := resultLog[0] vmessConfig := VmessConfig{ PORT: port, UUID: uuid, } // 执行模板渲染 var result bytes.Buffer if err := tmpl.Execute(&result, vmessConfig); err != nil { return false, []string{ err.Error(), } } // 将result写入到 /usr/local/etc/xray/config.json 中 // 直接访问底层字节切片避免拷贝 data := result.Bytes() // 快速验证JSON格式 if !json.Valid(data) { return false, []string{fmt.Sprintf("Invalid JSON format: %s", data)} } // 使用适当权限创建文件并写入(O_WRONLY|O_CREATE|O_TRUNC, 0644) filename := "/usr/local/etc/xray/config.json" if err := os.WriteFile(filename, data, 0644); err != nil { return false, []string{err.Error()} } fmt.Println("xray config file is written to ", filename) // 移除encode自动添加的换行,重新缩进格式化 var prettyJSON bytes.Buffer if err := json.Indent(&prettyJSON, bytes.TrimSpace(data), "", " "); err != nil { fmt.Printf("JSON indent error: %v\n", err) } fmt.Println(prettyJSON.String()) fmt.Println() // 重启Xray op.SystemdRestart("xray") ok, resultLog = op.SystemIsRunning("xray") if !ok { log.Error("Xray service is not running => %s Maybe the config file is not valid", resultLog) return false, resultLog } result.Reset() // 清空全局buffer以备后续使用 // 输出 client的配置 configCache := config.ConfigCache // 获取服务器节点名称 serverNodeName := configCache.Agent.OS.Hostname vmessClientConfig := VmessClientConfig{ ServerNodeName: serverNodeName, ServerNodeAddress: configCache.Agent.Network.Public.IPv4, VmessConfig: vmessConfig, } // 执行模板渲染 clientTmpl, err := template.New("vmessClientConfig").Parse(xray.VmessClientTemplate) if err != nil { return false, []string{err.Error()} } if err := clientTmpl.Execute(&result, vmessClientConfig); err != nil { return false, []string{ err.Error(), } } // 将result 打印的终端 fmt.Println("vmess client config is below: ") fmt.Println(string(result.Bytes())) fmt.Println() return true, []string{"Xray Configuration file written successfully"} } // 安装Xray 最新版本 主机可以联网才可以 func installXray() { installScriptUrl := "https://gitea.107421.xyz/zeaslity/Xray-install/raw/branch/main/install-release.sh" // 下载安装脚本 ok, err := utils.DownloadFile(installScriptUrl, "/tmp/install-release.sh") if !ok { log.Error("Download Xray install script failed ! from %s error is %s", installScriptUrl, err) return } // 添加执行权限 os.Chmod("/tmp/install-release.sh", 0777) // 执行安装脚本 op.SingleLineCommandExecutor([]string{ "/bin/bash", "/tmp/install-release.sh", "-u root", "install", }) op.SystemdUp("xray") op.SystemdEnable("xray") // 默认服务已经启动! 检查 ok, resultLog := op.SystemIsRunning("xray") if !ok { log.Error("Xray service is not running => %s", resultLog) return } // 安装成功 log.Info("Xray installed successfully") }