初始化项目
This commit is contained in:
10
agent-wdd/cmd/Acme.go
Normal file
10
agent-wdd/cmd/Acme.go
Normal file
@@ -0,0 +1,10 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
// addAcmeSubcommands acme的相关任务
|
||||
func addAcmeSubcommands(cmd *cobra.Command) {
|
||||
|
||||
}
|
||||
1087
agent-wdd/cmd/Base.go
Normal file
1087
agent-wdd/cmd/Base.go
Normal file
File diff suppressed because it is too large
Load Diff
30
agent-wdd/cmd/Config.go
Normal file
30
agent-wdd/cmd/Config.go
Normal file
@@ -0,0 +1,30 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"agent-wdd/config"
|
||||
"agent-wdd/log"
|
||||
"agent-wdd/utils"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
func addConfigSubcommands(cmd *cobra.Command) {
|
||||
|
||||
showConfigCmd := &cobra.Command{
|
||||
Use: "show",
|
||||
Short: "显示agent运行配置",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
log.Info("显示agent运行配置")
|
||||
|
||||
content := utils.ReadAllContentFromFile(config.WddConfigFilePath)
|
||||
|
||||
utils.BeautifulPrintListWithTitle(content, "agent运行配置")
|
||||
|
||||
log.Info("显示agent运行配置完成")
|
||||
|
||||
},
|
||||
}
|
||||
|
||||
cmd.AddCommand(showConfigCmd)
|
||||
|
||||
}
|
||||
122
agent-wdd/cmd/Download.go
Normal file
122
agent-wdd/cmd/Download.go
Normal file
@@ -0,0 +1,122 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"agent-wdd/log"
|
||||
"agent-wdd/utils"
|
||||
"context"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"time"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"golang.org/x/net/proxy"
|
||||
)
|
||||
|
||||
// 示例:添加download子命令
|
||||
func addDownloadSubcommands(cmd *cobra.Command) {
|
||||
proxyCmd := &cobra.Command{
|
||||
Use: "proxy [proxyUrl] [url] [dest]",
|
||||
Short: "使用代理下载 socks5://[username]:[password]@ip:port http://[username]:[password]@ip:port",
|
||||
Args: cobra.ExactArgs(3),
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
proxyURL := args[0]
|
||||
fileURL := args[1]
|
||||
destPath := args[2]
|
||||
|
||||
log.Info("Downloading using proxy: %s -> from %s to %s\n", proxyURL, fileURL, destPath)
|
||||
|
||||
// 创建带代理的HTTP客户端
|
||||
client, err := createProxyClient(proxyURL)
|
||||
if err != nil {
|
||||
log.Error("创建代理客户端失败: %v", err)
|
||||
}
|
||||
|
||||
// 执行下载
|
||||
downloadOk, resultLog := utils.DownloadFileWithClient(client, fileURL, destPath)
|
||||
if !downloadOk {
|
||||
log.Error("下载失败: %v", resultLog)
|
||||
} else {
|
||||
log.Info("文件下载完成")
|
||||
}
|
||||
|
||||
},
|
||||
}
|
||||
|
||||
cmd.Run = func(cmd *cobra.Command, args []string) {
|
||||
|
||||
if len(args) == 0 {
|
||||
log.Error("请输入下载地址")
|
||||
return
|
||||
} else if len(args) == 1 {
|
||||
timeString := utils.CurrentTimeString()
|
||||
args = append(args, "./"+timeString+".txt")
|
||||
}
|
||||
|
||||
log.Info("Downloading without proxy: %s -> %s\n", args[0], args[1])
|
||||
|
||||
downloadOk, resultLog := utils.DownloadFile(args[0], args[1])
|
||||
if !downloadOk {
|
||||
log.Error("下载失败: %s", resultLog)
|
||||
} else {
|
||||
log.Info("下载成功: %s", args[1])
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
cmd.AddCommand(proxyCmd)
|
||||
}
|
||||
|
||||
// 创建带代理的HTTP客户端
|
||||
func createProxyClient(proxyURL string) (*http.Client, error) {
|
||||
parsedURL, err := url.Parse(proxyURL)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("无效的代理URL: %w", err)
|
||||
}
|
||||
|
||||
switch parsedURL.Scheme {
|
||||
case "socks5":
|
||||
return createSocks5Client(parsedURL)
|
||||
case "http", "https":
|
||||
return createHTTPClient(parsedURL), nil
|
||||
default:
|
||||
return nil, fmt.Errorf("不支持的代理协议: %s", parsedURL.Scheme)
|
||||
}
|
||||
}
|
||||
|
||||
// 创建SOCKS5代理客户端
|
||||
func createSocks5Client(proxyURL *url.URL) (*http.Client, error) {
|
||||
var auth *proxy.Auth
|
||||
if proxyURL.User != nil {
|
||||
password, _ := proxyURL.User.Password()
|
||||
auth = &proxy.Auth{
|
||||
User: proxyURL.User.Username(),
|
||||
Password: password,
|
||||
}
|
||||
}
|
||||
|
||||
dialer, err := proxy.SOCKS5("tcp", proxyURL.Host, auth, proxy.Direct)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("创建SOCKS5拨号器失败: %w", err)
|
||||
}
|
||||
|
||||
return &http.Client{
|
||||
Transport: &http.Transport{
|
||||
DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
|
||||
return dialer.Dial(network, addr)
|
||||
},
|
||||
},
|
||||
Timeout: 10 * time.Second,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// 创建HTTP代理客户端
|
||||
func createHTTPClient(proxyURL *url.URL) *http.Client {
|
||||
return &http.Client{
|
||||
Transport: &http.Transport{
|
||||
Proxy: http.ProxyURL(proxyURL),
|
||||
},
|
||||
Timeout: 30 * time.Minute,
|
||||
}
|
||||
}
|
||||
98
agent-wdd/cmd/Info.go
Normal file
98
agent-wdd/cmd/Info.go
Normal file
@@ -0,0 +1,98 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"agent-wdd/config"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
func addInfoSubcommands(cmd *cobra.Command) {
|
||||
|
||||
// 操作系统
|
||||
os := &cobra.Command{
|
||||
Use: "os",
|
||||
Short: "主机操作系统相关的信息",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
os := config.ConfigCache.Agent.OS
|
||||
os.Gather()
|
||||
|
||||
os.SaveConfig()
|
||||
},
|
||||
}
|
||||
|
||||
// network
|
||||
network := &cobra.Command{
|
||||
Use: "network",
|
||||
Short: "主机Network相关的信息",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
network := config.ConfigCache.Agent.Network
|
||||
network.Gather()
|
||||
network.SaveConfig()
|
||||
},
|
||||
}
|
||||
|
||||
// cpu
|
||||
cpu := &cobra.Command{
|
||||
Use: "cpu",
|
||||
Short: "主机cpu相关的信息",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
cpu := config.ConfigCache.Agent.CPU
|
||||
cpu.Gather()
|
||||
cpu.Save()
|
||||
},
|
||||
}
|
||||
|
||||
// memory
|
||||
memory := &cobra.Command{
|
||||
Use: "mem",
|
||||
Short: "主机memory相关的信息",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
mem := config.ConfigCache.Agent.Mem
|
||||
mem.Gather()
|
||||
swap := config.ConfigCache.Agent.Swap
|
||||
swap.Gather()
|
||||
|
||||
mem.SaveConfig()
|
||||
swap.SaveConfig()
|
||||
|
||||
},
|
||||
}
|
||||
|
||||
// disk
|
||||
disk := &cobra.Command{
|
||||
Use: "disk",
|
||||
Short: "主机disk相关的信息",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
//disks := config.ConfigCache.Agent.Disks
|
||||
config.DiskListGather()
|
||||
|
||||
config.DiskListSaveConfig()
|
||||
},
|
||||
}
|
||||
|
||||
// all全部的info
|
||||
all := &cobra.Command{
|
||||
Use: "all",
|
||||
Short: "主机全部相关的信息",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
// 执行所有info
|
||||
cpu.Run(cmd, args)
|
||||
os.Run(cmd, args)
|
||||
memory.Run(cmd, args)
|
||||
network.Run(cmd, args)
|
||||
disk.Run(cmd, args)
|
||||
|
||||
// 归一化
|
||||
config.ConfigCache.NormalizeConfig()
|
||||
},
|
||||
}
|
||||
|
||||
cmd.AddCommand(
|
||||
all,
|
||||
os,
|
||||
cpu,
|
||||
memory,
|
||||
network,
|
||||
disk,
|
||||
)
|
||||
}
|
||||
310
agent-wdd/cmd/Proxy.go
Normal file
310
agent-wdd/cmd/Proxy.go
Normal file
@@ -0,0 +1,310 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"agent-wdd/cmd/xray"
|
||||
"agent-wdd/config"
|
||||
"agent-wdd/log"
|
||||
"agent-wdd/op"
|
||||
"agent-wdd/utils"
|
||||
"bytes"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
"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()
|
||||
},
|
||||
},
|
||||
&cobra.Command{
|
||||
Use: "remove",
|
||||
Short: "移除Xray",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
log.Info("Removing Xray...")
|
||||
|
||||
removeXray()
|
||||
},
|
||||
},
|
||||
// 其他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子命令...
|
||||
)
|
||||
}
|
||||
|
||||
// 移除Xray
|
||||
func removeXray() {
|
||||
|
||||
}
|
||||
|
||||
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(),
|
||||
}
|
||||
}
|
||||
|
||||
lines := strings.Split(string(result.Bytes()), "\n")
|
||||
|
||||
// for index, line := range lines {
|
||||
// fmt.Println(index, line)
|
||||
// }
|
||||
|
||||
// 转换为字节切片并进行Base64编码
|
||||
v2rayNGConfig := "vmess://" + base64.StdEncoding.EncodeToString([]byte(lines[2]))
|
||||
|
||||
// 将result 打印的终端
|
||||
fmt.Println("Clash client config is below: ")
|
||||
fmt.Println()
|
||||
fmt.Println(lines[1])
|
||||
fmt.Println()
|
||||
fmt.Println("V2rayNG config is below: ")
|
||||
fmt.Println()
|
||||
fmt.Println(v2rayNGConfig)
|
||||
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)
|
||||
|
||||
// 执行安装脚本
|
||||
ok, resultLog := op.SingleLineCommandExecutor([]string{"/bin/bash", "/tmp/install-release.sh", "-u", "root", "install"})
|
||||
if !ok {
|
||||
log.Error("Install Xray failed ! error is %s", resultLog)
|
||||
return
|
||||
}
|
||||
|
||||
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")
|
||||
|
||||
}
|
||||
7
agent-wdd/cmd/WddHost.go
Normal file
7
agent-wdd/cmd/WddHost.go
Normal file
@@ -0,0 +1,7 @@
|
||||
package cmd
|
||||
|
||||
import "github.com/spf13/cobra"
|
||||
|
||||
func addWddSubcommands(cmd *cobra.Command) {
|
||||
|
||||
}
|
||||
152
agent-wdd/cmd/Zsh.go
Normal file
152
agent-wdd/cmd/Zsh.go
Normal file
@@ -0,0 +1,152 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"agent-wdd/config"
|
||||
"agent-wdd/log"
|
||||
"agent-wdd/op"
|
||||
"agent-wdd/utils"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
func addZshSubcommands(cmd *cobra.Command) {
|
||||
cmd.Run = func(cmd *cobra.Command, args []string) {
|
||||
log.Info("安装zsh")
|
||||
|
||||
// 初始化安装命令
|
||||
utils.CreateFolder("/root/wdd")
|
||||
|
||||
if config.CanConnectInternet() <= 1 {
|
||||
log.Error("无法连接互联网,无法安装zsh")
|
||||
return
|
||||
}
|
||||
|
||||
// 判定config
|
||||
if config.ConfigCache.Agent.Network.Public.IPv4 == "" {
|
||||
network := config.ConfigCache.Agent.Network
|
||||
network.Gather()
|
||||
network.SaveConfig()
|
||||
}
|
||||
|
||||
// 下载并安装zsh和git
|
||||
ok := op.AgentPackOperator.Install([]string{"git", "zsh"})
|
||||
if !ok {
|
||||
log.Error("安装git和zsh失败, 无法继续后面的的安装!")
|
||||
return
|
||||
}
|
||||
|
||||
// 清理残留
|
||||
utils.RemoveFolderComplete("/root/.oh-my-zsh")
|
||||
utils.RemoveFolderComplete("/root/wdd/zsh-install.sh")
|
||||
|
||||
ohMyZshInstallUrl := ""
|
||||
|
||||
if config.ConfigCache.Agent.Network.Internet == 7 {
|
||||
ohMyZshInstallUrl = "https://gitea.107421.xyz/zeaslity/ohmyzsh/raw/branch/master/tools/install.sh"
|
||||
} else {
|
||||
ohMyZshInstallUrl = "https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh"
|
||||
}
|
||||
|
||||
downloadOk, resultLog := utils.DownloadFile(ohMyZshInstallUrl, "/root/wdd/zsh-install.sh")
|
||||
if !downloadOk {
|
||||
log.Error("下载zsh安装脚本失败: %v", resultLog)
|
||||
return
|
||||
}
|
||||
|
||||
op.SingleLineCommandExecutor([]string{
|
||||
"chmod",
|
||||
"+x",
|
||||
"/root/wdd/zsh-install.sh",
|
||||
})
|
||||
|
||||
installZshCommand := []string{
|
||||
"sh",
|
||||
"-c",
|
||||
"/root/wdd/zsh-install.sh",
|
||||
}
|
||||
|
||||
if config.ConfigCache.Agent.Network.Internet == 7 {
|
||||
op.SingleLineCommandExecutor([]string{
|
||||
"export",
|
||||
"REMOTE=https://gitea.107421.xyz/zeaslity/ohmyzsh.git",
|
||||
})
|
||||
}
|
||||
|
||||
// 执行 oh-my-zsh 安装命令
|
||||
op.RealTimeCommandExecutor(installZshCommand)
|
||||
|
||||
log.Info("安装zsh完成, 开始安装插件!")
|
||||
|
||||
pluginsHardCodeUrl := [][]string{
|
||||
{
|
||||
"https://gitee.com/wangl-cc/zsh-autosuggestions.git",
|
||||
"/root/.oh-my-zsh/plugins/zsh-autosuggestions",
|
||||
},
|
||||
{
|
||||
"https://gitee.com/xiaoqqya/zsh-syntax-highlighting.git",
|
||||
"/root/.oh-my-zsh/plugins/zsh-syntax-highlighting",
|
||||
},
|
||||
}
|
||||
|
||||
pluginsHardCodeOutsideUrl := [][]string{
|
||||
{
|
||||
"https://github.com/zsh-users/zsh-autosuggestions",
|
||||
"/root/.oh-my-zsh/plugins/zsh-autosuggestions",
|
||||
},
|
||||
{
|
||||
"https://github.com/zsh-users/zsh-syntax-highlighting.git",
|
||||
"/root/.oh-my-zsh/plugins/zsh-syntax-highlighting",
|
||||
},
|
||||
}
|
||||
|
||||
pluginsListUrl := []string{
|
||||
"https://gitea.107421.xyz/zeaslity/ohmyzsh/src/branch/master/plugins/command-not-found/command-not-found.plugin.zsh",
|
||||
"https://gitea.107421.xyz/zeaslity/ohmyzsh/src/branch/master/plugins/autojump/autojump.plugin.zsh",
|
||||
"https://gitea.107421.xyz/zeaslity/ohmyzsh/src/branch/master/plugins/themes/themes.plugin.zsh",
|
||||
}
|
||||
|
||||
// 下载插件
|
||||
if config.ConfigCache.Agent.Network.Internet == 7 {
|
||||
// 执行硬编码命令, 安装插件
|
||||
for _, command := range pluginsHardCodeUrl {
|
||||
op.SingleLineCommandExecutor([]string{"git", "clone", command[0], command[1]})
|
||||
}
|
||||
|
||||
} else {
|
||||
// 执行硬编码命令, 安装插件 国外
|
||||
for _, command := range pluginsHardCodeOutsideUrl {
|
||||
op.SingleLineCommandExecutor([]string{"git", "clone", command[0], command[1]})
|
||||
}
|
||||
}
|
||||
// 下载插件
|
||||
for _, url := range pluginsListUrl {
|
||||
downloadOk, resultLog := utils.DownloadFile(url, "/root/.oh-my-zsh/plugins/")
|
||||
if !downloadOk {
|
||||
log.Error("下载插件失败: %v", resultLog)
|
||||
}
|
||||
}
|
||||
|
||||
// 修改ZSH配置
|
||||
utils.FindAndReplaceContentInFile("robbyrussell", "agnoster", "/root/.zshrc")
|
||||
utils.FindAndReplaceContentInFile("# DISABLE_AUTO_UPDATE=\"true\"", "DISABLE_AUTO_UPDATE=\"true\"", "/root/.zshrc")
|
||||
utils.FindAndReplaceContentInFile("plugins=(git)", "plugins=(git zsh-autosuggestions zsh-syntax-highlighting command-not-found z themes)", "/root/.zshrc")
|
||||
|
||||
//
|
||||
op.SingleLineCommandExecutor([]string{
|
||||
"source",
|
||||
"/root/.zshrc",
|
||||
})
|
||||
|
||||
op.SingleLineCommandExecutor([]string{
|
||||
"chsh",
|
||||
"-s",
|
||||
"/bin/zsh",
|
||||
})
|
||||
|
||||
op.SingleLineCommandExecutor([]string{
|
||||
"zsh",
|
||||
})
|
||||
|
||||
log.Info("Zsh安装完成")
|
||||
}
|
||||
}
|
||||
121
agent-wdd/cmd/beans/DockerDaemonConfig.go
Normal file
121
agent-wdd/cmd/beans/DockerDaemonConfig.go
Normal file
@@ -0,0 +1,121 @@
|
||||
package beans
|
||||
|
||||
var ContainerdServiceFile = "/lib/systemd/system/containerd.service"
|
||||
var DockerSocketFile = "/lib/systemd/system/docker.socket"
|
||||
var DockerServiceFile = "/lib/systemd/system/docker.service"
|
||||
|
||||
var ContainerdDaemonService = `
|
||||
# Copyright The containerd Authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
[Unit]
|
||||
Description=containerd container runtime
|
||||
Documentation=https://containerd.io
|
||||
After=network.target local-fs.target
|
||||
|
||||
[Service]
|
||||
ExecStartPre=-/sbin/modprobe overlay
|
||||
ExecStart=/usr/bin/containerd
|
||||
|
||||
Type=notify
|
||||
Delegate=yes
|
||||
KillMode=process
|
||||
Restart=always
|
||||
RestartSec=5
|
||||
# Having non-zero Limit*s causes performance problems due to accounting overhead
|
||||
# in the kernel. We recommend using cgroups to do container-local accounting.
|
||||
LimitNPROC=infinity
|
||||
LimitCORE=infinity
|
||||
LimitNOFILE=infinity
|
||||
# Comment TasksMax if your systemd version does not supports it.
|
||||
# Only systemd 226 and above support this version.
|
||||
TasksMax=infinity
|
||||
OOMScoreAdjust=-999
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
`
|
||||
|
||||
var DockerSocketDaemonService = `
|
||||
[Unit]
|
||||
Description=Docker Socket for the API
|
||||
|
||||
[Socket]
|
||||
ListenStream=/var/run/docker.sock
|
||||
SocketMode=0660
|
||||
SocketUser=root
|
||||
SocketGroup=docker
|
||||
|
||||
[Install]
|
||||
WantedBy=sockets.target
|
||||
`
|
||||
|
||||
var DockerDaemonService = `
|
||||
[Unit]
|
||||
Description=Docker Application Container Engine
|
||||
Documentation=https://docs.docker.com
|
||||
After=network-online.target docker.socket firewalld.service containerd.service
|
||||
Wants=network-online.target
|
||||
Requires=docker.socket containerd.service
|
||||
|
||||
[Service]
|
||||
Type=notify
|
||||
# the default is not to use systemd for cgroups because the delegate issues still
|
||||
# exists and systemd currently does not support the cgroup feature set required
|
||||
# for containers run by docker
|
||||
ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
|
||||
ExecReload=/bin/kill -s HUP $MAINPID
|
||||
TimeoutSec=0
|
||||
RestartSec=2
|
||||
Restart=always
|
||||
|
||||
# Note that StartLimit* options were moved from "Service" to "Unit" in systemd 229.
|
||||
# Both the old, and new location are accepted by systemd 229 and up, so using the old location
|
||||
# to make them work for either version of systemd.
|
||||
StartLimitBurst=3
|
||||
|
||||
# Note that StartLimitInterval was renamed to StartLimitIntervalSec in systemd 230.
|
||||
# Both the old, and new name are accepted by systemd 230 and up, so using the old name to make
|
||||
# this option work for either version of systemd.
|
||||
StartLimitInterval=60s
|
||||
|
||||
# Having non-zero Limit*s causes performance problems due to accounting overhead
|
||||
# in the kernel. We recommend using cgroups to do container-local accounting.
|
||||
LimitNOFILE=infinity
|
||||
LimitNPROC=infinity
|
||||
LimitCORE=infinity
|
||||
|
||||
# Comment TasksMax if your systemd version does not support it.
|
||||
# Only systemd 226 and above support this option.
|
||||
TasksMax=infinity
|
||||
|
||||
# set delegate yes so that systemd does not reset the cgroups of docker containers
|
||||
Delegate=yes
|
||||
|
||||
# kill only the docker process, not all processes in the cgroup
|
||||
KillMode=process
|
||||
OOMScoreAdjust=-500
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
`
|
||||
|
||||
var DockerDeamonConfig = `
|
||||
{
|
||||
"insecure-registries": [
|
||||
"DockerRegisterDomain:8033",
|
||||
"harbor.wdd.io:8033"
|
||||
]
|
||||
}
|
||||
`
|
||||
54
agent-wdd/cmd/beans/HarborConfig.go
Normal file
54
agent-wdd/cmd/beans/HarborConfig.go
Normal file
@@ -0,0 +1,54 @@
|
||||
package beans
|
||||
|
||||
// HarborYamlConfig 是harbor的配置文件
|
||||
var HarborYamlConfig = `
|
||||
hostname: HarborHostName
|
||||
|
||||
http:
|
||||
port: 8033
|
||||
|
||||
harbor_admin_password: V2ryStr@ngPss
|
||||
|
||||
database:
|
||||
password: V2ryStr@ngPss
|
||||
max_idle_conns: 50
|
||||
max_open_conns: 1000
|
||||
conn_max_lifetime: 3600
|
||||
conn_max_idle_time: 3600
|
||||
|
||||
data_volume: /var/lib/docker/harbor-data
|
||||
|
||||
jobservice:
|
||||
max_job_workers: 10
|
||||
job_loggers:
|
||||
- STD_OUTPUT
|
||||
- FILE
|
||||
logger_sweeper_duration: 3
|
||||
|
||||
notification:
|
||||
webhook_job_max_retry: 10
|
||||
webhook_job_http_client_timeout: 10
|
||||
|
||||
|
||||
log:
|
||||
level: warning
|
||||
local:
|
||||
rotate_count: 50
|
||||
rotate_size: 200M
|
||||
location: /var/log/harbor
|
||||
|
||||
cache:
|
||||
enabled: false
|
||||
expire_hours: 24
|
||||
|
||||
_version: 2.9.0
|
||||
|
||||
proxy:
|
||||
http_proxy:
|
||||
https_proxy:
|
||||
no_proxy:
|
||||
components:
|
||||
- core
|
||||
- jobservice
|
||||
- trivy
|
||||
`
|
||||
203
agent-wdd/cmd/beans/SshSysConfig.go
Normal file
203
agent-wdd/cmd/beans/SshSysConfig.go
Normal file
@@ -0,0 +1,203 @@
|
||||
package beans
|
||||
|
||||
var Ed25519PrivateKey = `-----BEGIN OPENSSH PRIVATE KEY-----
|
||||
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW
|
||||
QyNTUxOQAAACDk8R4KXGgDa5H2r8HrqW1klShoSISV20sLiXZPZPfeLwAAAJCIan+LiGp/
|
||||
iwAAAAtzc2gtZWQyNTUxOQAAACDk8R4KXGgDa5H2r8HrqW1klShoSISV20sLiXZPZPfeLw
|
||||
AAAEDhnul+q0TNTgrO9kfmGsFhtn/rGRIrmhFostjem/QlZuTxHgpcaANrkfavweupbWSV
|
||||
KGhIhJXbSwuJdk9k994vAAAADHdkZEBjbWlpLmNvbQE=
|
||||
-----END OPENSSH PRIVATE KEY-----
|
||||
`
|
||||
|
||||
var Ed25519PublicKey = `ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOTxHgpcaANrkfavweupbWSVKGhIhJXbSwuJdk9k994v wdd@cmii.com
|
||||
`
|
||||
|
||||
var DefaultSshdConfig = `
|
||||
# OCTOPUS AGENT DEFAULT SSHD CONFIG - WDD
|
||||
|
||||
# This is the sshd server system-wide configuration file. See
|
||||
# sshd_config(5) for more information.
|
||||
|
||||
# This sshd was compiled with PATH=/usr/bin:/bin:/usr/sbin:/sbin
|
||||
|
||||
# The strategy used for options in the default sshd_config shipped with
|
||||
# OpenSSH is to specify options with their default value where
|
||||
# possible, but leave them commented. Uncommented options override the
|
||||
# default value.
|
||||
|
||||
#Include /etc/ssh/sshd_config.d/*.conf
|
||||
|
||||
Port 22
|
||||
Port 22333
|
||||
AddressFamily any
|
||||
ListenAddress 0.0.0.0
|
||||
ListenAddress ::
|
||||
|
||||
#HostKey /etc/ssh/ssh_host_rsa_key
|
||||
#HostKey /etc/ssh/ssh_host_ecdsa_key
|
||||
#HostKey /etc/ssh/ssh_host_ed25519_key
|
||||
|
||||
# Ciphers and keying
|
||||
#RekeyLimit default none
|
||||
|
||||
# Logging
|
||||
#SyslogFacility AUTH
|
||||
#LogLevel INFO
|
||||
|
||||
# Authentication:
|
||||
|
||||
#LoginGraceTime 2m
|
||||
#PermitRootLogin prohibit-password
|
||||
#StrictModes yes
|
||||
#MaxAuthTries 6
|
||||
#MaxSessions 10
|
||||
|
||||
#PubkeyAuthentication yes
|
||||
|
||||
# Expect .ssh/authorized_keys2 to be disregarded by default in future.
|
||||
#AuthorizedKeysFile .ssh/authorized_keys .ssh/authorized_keys2
|
||||
|
||||
#AuthorizedPrincipalsFile none
|
||||
|
||||
#AuthorizedKeysCommand none
|
||||
#AuthorizedKeysCommandUser nobody
|
||||
|
||||
# For this to work you will also need host keys in /etc/ssh/ssh_known_hosts
|
||||
#HostbasedAuthentication no
|
||||
# Change to yes if you don't trust ~/.ssh/known_hosts for
|
||||
# HostbasedAuthentication
|
||||
#IgnoreUserKnownHosts no
|
||||
# Don't read the user's ~/.rhosts and ~/.shosts files
|
||||
#IgnoreRhosts yes
|
||||
|
||||
# To disable tunneled clear text passwords, change to no here!
|
||||
#PasswordAuthentication yes
|
||||
PermitEmptyPasswords no
|
||||
|
||||
# Change to yes to enable challenge-response passwords (beware issues with
|
||||
# some PAM modules and threads)
|
||||
ChallengeResponseAuthentication no
|
||||
|
||||
# Kerberos options
|
||||
#KerberosAuthentication no
|
||||
#KerberosOrLocalPasswd yes
|
||||
#KerberosTicketCleanup yes
|
||||
#KerberosGetAFSToken no
|
||||
|
||||
# GSSAPI options
|
||||
#GSSAPIAuthentication no
|
||||
#GSSAPICleanupCredentials yes
|
||||
#GSSAPIStrictAcceptorCheck yes
|
||||
#GSSAPIKeyExchange no
|
||||
|
||||
# Set this to 'yes' to enable PAM authentication, account processing,
|
||||
# and session processing. If this is enabled, PAM authentication will
|
||||
# be allowed through the ChallengeResponseAuthentication and
|
||||
# PasswordAuthentication. Depending on your PAM configuration,
|
||||
# PAM authentication via ChallengeResponseAuthentication may bypass
|
||||
# the setting of "PermitRootLogin without-password".
|
||||
# If you just want the PAM account and session checks to run without
|
||||
# PAM authentication, then enable this but set PasswordAuthentication
|
||||
# and ChallengeResponseAuthentication to 'no'.
|
||||
UsePAM yes
|
||||
|
||||
AllowAgentForwarding yes
|
||||
AllowTcpForwarding yes
|
||||
#GatewayPorts no
|
||||
X11Forwarding yes
|
||||
#X11DisplayOffset 10
|
||||
#X11UseLocalhost yes
|
||||
#PermitTTY yes
|
||||
PrintMotd no
|
||||
#PrintLastLog yes
|
||||
TCPKeepAlive yes
|
||||
#PermitUserEnvironment no
|
||||
#Compression delayed
|
||||
#ClientAliveInterval 0
|
||||
#ClientAliveCountMax 3
|
||||
#UseDNS no
|
||||
#PidFile /var/run/sshd.pid
|
||||
#MaxStartups 10:30:100
|
||||
#PermitTunnel no
|
||||
#ChrootDirectory none
|
||||
#VersionAddendum none
|
||||
|
||||
# no default banner path
|
||||
#Banner none
|
||||
|
||||
# Allow client to pass locale environment variables
|
||||
AcceptEnv LANG LC_*
|
||||
|
||||
# override default of no subsystems
|
||||
Subsystem sftp /usr/lib/openssh/sftp-server
|
||||
|
||||
# Example of overriding settings on a per-user basis
|
||||
#Match User anoncvs
|
||||
# X11Forwarding no
|
||||
# AllowTcpForwarding no
|
||||
# PermitTTY no
|
||||
# ForceCommand cvs server
|
||||
PasswordAuthentication yes
|
||||
PermitRootLogin yes
|
||||
StrictModes no
|
||||
ClientAliveInterval 30
|
||||
ClientAliveCountMax 60
|
||||
`
|
||||
|
||||
var SysctlConfig = `
|
||||
# 开启 IPv4 路由转发
|
||||
net.ipv4.ip_forward = 1
|
||||
|
||||
# 禁用 IPv6
|
||||
net.ipv6.conf.all.disable_ipv6 = 1
|
||||
net.ipv6.conf.default.disable_ipv6 = 1
|
||||
|
||||
# 开启 IPv4 转发
|
||||
net.ipv4.conf.all.forwarding = 1
|
||||
net.ipv4.conf.default.forwarding = 1
|
||||
|
||||
# 开启 IPv4 连接跟踪
|
||||
net.ipv4.tcp_syncookies = 1
|
||||
|
||||
# 开启 IPv4 连接跟踪
|
||||
net.ipv4.tcp_tw_recycle = 1
|
||||
|
||||
# 开启 IPv4 连接跟踪
|
||||
net.ipv4.tcp_tw_reuse = 1
|
||||
|
||||
# 开启 IPv4 连接跟踪
|
||||
net.ipv4.tcp_fin_timeout = 30
|
||||
|
||||
# 开启 IPv4 连接跟踪
|
||||
net.ipv4.tcp_keepalive_time = 1200
|
||||
|
||||
# 开启 IPv4 连接跟踪
|
||||
net.ipv4.ip_local_port_range = 1024 65535
|
||||
|
||||
# 开启 IPv4 连接跟踪
|
||||
net.ipv4.tcp_max_syn_backlog = 8192
|
||||
|
||||
# 开启 IPv4 连接跟踪
|
||||
net.ipv4.tcp_max_tw_buckets = 5000
|
||||
|
||||
# 开启 IPv4 连接跟踪
|
||||
net.ipv4.tcp_max_orphans = 32768
|
||||
|
||||
# 开启 IPv4 连接跟踪
|
||||
net.ipv4.tcp_synack_retries = 2
|
||||
|
||||
# 开启 IPv4 连接跟踪
|
||||
net.ipv4.tcp_syn_retries = 2
|
||||
|
||||
# 开启 IPv4 连接跟踪
|
||||
net.ipv4.tcp_synflood_protect = 1000
|
||||
|
||||
# 开启 IPv4 连接跟踪
|
||||
net.ipv4.tcp_timestamps = 1
|
||||
|
||||
# 开启 IPv4 连接跟踪
|
||||
net.ipv4.tcp_window_scaling = 1
|
||||
|
||||
# 开启 IPv4 连接跟踪
|
||||
net.ipv4.tcp_rmem = 4096 87380 4194304
|
||||
`
|
||||
173
agent-wdd/cmd/root.go
Normal file
173
agent-wdd/cmd/root.go
Normal file
@@ -0,0 +1,173 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"agent-wdd/config"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var rootCmd = &cobra.Command{
|
||||
Use: "wdd",
|
||||
Short: "wdd应用程序是wdd封装的NB工具",
|
||||
Long: `使用golang的强大特性,加上 WDD 的高超技术,打造一个方便、高效、适用于各种LINUX系统的瑞士军刀工具!
|
||||
尽情享用! 尽情享用! 尽情享用!`,
|
||||
DisableAutoGenTag: true,
|
||||
CompletionOptions: cobra.CompletionOptions{
|
||||
DisableDefaultCmd: true,
|
||||
DisableNoDescFlag: true,
|
||||
DisableDescriptions: true,
|
||||
HiddenDefaultCmd: true,
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
// 初始化配置
|
||||
cobra.OnInitialize(config.InitConfig)
|
||||
}
|
||||
|
||||
func Execute() {
|
||||
|
||||
// 1. base命令
|
||||
baseCmd := &cobra.Command{
|
||||
Use: "base",
|
||||
Short: "服务器基础操作",
|
||||
}
|
||||
addBaseSubcommands(baseCmd)
|
||||
|
||||
// 2. zsh命令
|
||||
zshCmd := &cobra.Command{
|
||||
Use: "zsh",
|
||||
Short: "zsh相关的内容",
|
||||
}
|
||||
addZshSubcommands(zshCmd)
|
||||
|
||||
// 3. proxy命令
|
||||
proxyCmd := &cobra.Command{
|
||||
Use: "proxy",
|
||||
Short: "主机代理相关的内容",
|
||||
}
|
||||
addProxySubcommands(proxyCmd)
|
||||
|
||||
// 4. acme命令
|
||||
acmeCmd := &cobra.Command{
|
||||
Use: "acme",
|
||||
Short: "acme相关的内容",
|
||||
}
|
||||
addAcmeSubcommands(acmeCmd)
|
||||
|
||||
// 5. wdd命令
|
||||
wddCmd := &cobra.Command{
|
||||
Use: "wdd",
|
||||
Short: "WDD相关操作",
|
||||
}
|
||||
addWddSubcommands(wddCmd)
|
||||
|
||||
// 6. security命令
|
||||
securityCmd := &cobra.Command{
|
||||
Use: "security",
|
||||
Short: "安全相关操作",
|
||||
}
|
||||
|
||||
// 7. info命令
|
||||
infoCmd := &cobra.Command{
|
||||
Use: "info",
|
||||
Short: "主机信息",
|
||||
}
|
||||
addInfoSubcommands(infoCmd)
|
||||
|
||||
// 8. version命令
|
||||
versionCmd := &cobra.Command{
|
||||
Use: "version",
|
||||
Short: "打印版本信息",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
// 实现version逻辑
|
||||
fmt.Println("版本信息: 1.0.0")
|
||||
},
|
||||
}
|
||||
|
||||
// 9. config命令
|
||||
configCmd := &cobra.Command{
|
||||
Use: "config",
|
||||
Short: "配置文件管理",
|
||||
}
|
||||
addConfigSubcommands(configCmd)
|
||||
|
||||
// 10. download命令
|
||||
downloadCmd := &cobra.Command{
|
||||
Use: "download",
|
||||
Short: "文件下载,直接下载 [url] [dest_path]",
|
||||
}
|
||||
|
||||
addDownloadSubcommands(downloadCmd)
|
||||
|
||||
helpCmd := &cobra.Command{
|
||||
Use: "help",
|
||||
Short: "帮助信息",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
// 在你的命令执行函数中
|
||||
// cmd.Root().SetHelpFunc(func(c *cobra.Command, s []string) {
|
||||
// // 直接使用默认帮助模板
|
||||
// c.Usage()
|
||||
// })
|
||||
|
||||
// 自定义实现 打印全部的命令
|
||||
printAllCommands(cmd.Root(), os.Stdout)
|
||||
},
|
||||
}
|
||||
|
||||
// 添加所有根命令
|
||||
rootCmd.AddCommand(
|
||||
baseCmd,
|
||||
zshCmd,
|
||||
proxyCmd,
|
||||
acmeCmd,
|
||||
wddCmd,
|
||||
securityCmd,
|
||||
infoCmd,
|
||||
versionCmd,
|
||||
configCmd,
|
||||
downloadCmd,
|
||||
helpCmd,
|
||||
)
|
||||
|
||||
if err := rootCmd.Execute(); err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func printAllCommands(cmd *cobra.Command, writer io.Writer) {
|
||||
// 打印命令标题
|
||||
fmt.Fprintf(writer, "All available commands:\n\n")
|
||||
|
||||
// 递归打印命令树
|
||||
var traverse func(*cobra.Command, int)
|
||||
traverse = func(c *cobra.Command, depth int) {
|
||||
if c.Hidden || c.Deprecated != "" {
|
||||
return
|
||||
}
|
||||
|
||||
// 生成命令前缀缩进
|
||||
indent := strings.Repeat(" ", depth)
|
||||
|
||||
// 打印当前命令信息
|
||||
fmt.Fprintf(writer, "%s%-20s%s\n",
|
||||
indent,
|
||||
c.Name(),
|
||||
strings.TrimSpace(c.Short))
|
||||
|
||||
// 递归子命令
|
||||
for _, subCmd := range c.Commands() {
|
||||
traverse(subCmd, depth+1)
|
||||
}
|
||||
}
|
||||
|
||||
// 从根命令开始遍历
|
||||
for _, c := range cmd.Commands() {
|
||||
traverse(c, 0)
|
||||
}
|
||||
}
|
||||
37
agent-wdd/cmd/xray/vmessTemplate.go
Normal file
37
agent-wdd/cmd/xray/vmessTemplate.go
Normal file
@@ -0,0 +1,37 @@
|
||||
package xray
|
||||
|
||||
var VmessServerTemplate = `
|
||||
{
|
||||
"log": {
|
||||
"loglevel": "warning"
|
||||
},
|
||||
"inbounds": [
|
||||
{
|
||||
"listen": "0.0.0.0",
|
||||
"port": {{.PORT}},
|
||||
"protocol": "vmess",
|
||||
"settings": {
|
||||
"clients": [
|
||||
{
|
||||
"id": "{{.UUID}}"
|
||||
}
|
||||
]
|
||||
},
|
||||
"streamSettings": {
|
||||
"network": "tcp"
|
||||
}
|
||||
}
|
||||
],
|
||||
"outbounds": [
|
||||
{
|
||||
"protocol": "freedom",
|
||||
"tag": "direct"
|
||||
}
|
||||
]
|
||||
}
|
||||
`
|
||||
|
||||
var VmessClientTemplate = `
|
||||
{"type":"vmess","name":"{{.ServerNodeName}}","server":"{{.ServerNodeAddress}}","port":{{.PORT}},"uuid":"{{.UUID}}","alterId":0,"cipher":"auto","network":"tcp"}
|
||||
{"v":"2","ps":"{{.ServerNodeName}}","add":"{{.ServerNodeAddress}}","port":{{.PORT}},"id":"{{.UUID}}","aid":0,"scy":"auto","net":"tcp"}
|
||||
`
|
||||
Reference in New Issue
Block a user