基础框架先行,编译器已无报错,项目正式创建
This commit is contained in:
@@ -0,0 +1,146 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"strings"
|
||||
"text/template"
|
||||
)
|
||||
|
||||
// frpc.toml 模板 - 完全复制你的配置文件结构
|
||||
const frpcTemplate = `serverAddr = "{{.ServerAddr}}"
|
||||
serverPort = {{.ServerPort}}
|
||||
|
||||
[auth]
|
||||
token = "{{.Token}}"
|
||||
|
||||
[log]
|
||||
to = "./frpc.log"
|
||||
level = "{{.LogLevel}}"
|
||||
maxDays = {{.LogMaxDays}}
|
||||
|
||||
[transport]
|
||||
tcpMux = {{.TcpMux}}
|
||||
tcpMuxKeepaliveInterval = {{.TcpMuxKeepalive}}
|
||||
heartbeatInterval = {{.HeartbeatInterval}}
|
||||
heartbeatTimeout = {{.HeartbeatTimeout}}
|
||||
poolCount = {{.PoolCount}}
|
||||
|
||||
{{range .Proxies}}
|
||||
[[proxies]]
|
||||
name = "{{.Name}}"
|
||||
type = "{{.Type}}"
|
||||
localIP = "{{.LocalIP}}"
|
||||
localPort = {{.LocalPort}}
|
||||
remotePort = {{.RemotePort}}
|
||||
{{end}}`
|
||||
|
||||
// 生成 frpc.toml 文件
|
||||
func GenerateFrpcConfig() error {
|
||||
// 1. 读取全局配置
|
||||
cfg, err := GetGlobalConfig()
|
||||
if err != nil {
|
||||
return fmt.Errorf("读取全局配置失败: %w", err)
|
||||
}
|
||||
|
||||
// 2. 读取所有启用的隧道
|
||||
proxies, err := GetProxies()
|
||||
if err != nil {
|
||||
return fmt.Errorf("读取隧道列表失败: %w", err)
|
||||
}
|
||||
|
||||
var activeProxies []Proxy
|
||||
for _, p := range proxies {
|
||||
if p.Enabled {
|
||||
activeProxies = append(activeProxies, p)
|
||||
}
|
||||
}
|
||||
|
||||
// 3. 组合数据
|
||||
data := struct {
|
||||
*GlobalConfig
|
||||
Proxies []Proxy
|
||||
}{
|
||||
GlobalConfig: cfg,
|
||||
Proxies: activeProxies,
|
||||
}
|
||||
|
||||
// 4. 渲染模板
|
||||
tmpl, err := template.New("frpc").Parse(frpcTemplate)
|
||||
if err != nil {
|
||||
return fmt.Errorf("解析模板失败: %w", err)
|
||||
}
|
||||
|
||||
var buf bytes.Buffer
|
||||
err = tmpl.Execute(&buf, data)
|
||||
if err != nil {
|
||||
return fmt.Errorf("渲染模板失败: %w", err)
|
||||
}
|
||||
|
||||
// 5. 写入文件
|
||||
err = os.WriteFile("./frpc.toml", buf.Bytes(), 0644)
|
||||
if err != nil {
|
||||
return fmt.Errorf("写入配置文件失败: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// 热加载 frpc
|
||||
func ReloadFrpc() error {
|
||||
// 先检查 frpc 进程是否在运行
|
||||
cmd := exec.Command("pgrep", "-f", "frpc")
|
||||
output, err := cmd.Output()
|
||||
if err != nil || len(output) == 0 {
|
||||
// frpc 没在运行,尝试启动
|
||||
return StartFrpc()
|
||||
}
|
||||
|
||||
// 执行 reload
|
||||
reloadCmd := exec.Command("frpc", "reload", "-c", "./frpc.toml")
|
||||
output, err = reloadCmd.CombinedOutput()
|
||||
if err != nil {
|
||||
return fmt.Errorf("reload 失败: %s, %w", string(output), err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// 启动 frpc
|
||||
func StartFrpc() error {
|
||||
// 先确保配置文件存在
|
||||
if _, err := os.Stat("./frpc.toml"); os.IsNotExist(err) {
|
||||
if err := GenerateFrpcConfig(); err != nil {
|
||||
return fmt.Errorf("生成配置文件失败: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
cmd := exec.Command("frpc", "-c", "./frpc.toml")
|
||||
// 后台运行,不阻塞
|
||||
err := cmd.Start()
|
||||
if err != nil {
|
||||
return fmt.Errorf("启动 frpc 失败: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// StopFrpc 停止 frpc
|
||||
func StopFrpc() error {
|
||||
cmd := exec.Command("pkill", "-f", "frpc")
|
||||
err := cmd.Run()
|
||||
if err != nil && !strings.Contains(err.Error(), "no process") {
|
||||
return fmt.Errorf("停止 frpc 失败: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// 检查 frpc 状态
|
||||
func GetFrpcStatus() (bool, error) {
|
||||
cmd := exec.Command("pgrep", "-f", "frpc")
|
||||
output, err := cmd.Output()
|
||||
if err != nil {
|
||||
return false, nil
|
||||
}
|
||||
return len(output) > 0, nil
|
||||
}
|
||||
Reference in New Issue
Block a user