后端已跑通
This commit is contained in:
Binary file not shown.
@@ -2,13 +2,51 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"embed"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
|
"syscall"
|
||||||
"text/template"
|
"text/template"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
//go:embed bin/*
|
||||||
|
var embeddedFrpc embed.FS
|
||||||
|
|
||||||
|
// 获取当前平台对应的 frpc 路径(从 embed 解压到临时目录)
|
||||||
|
func getFrpcPath() (string, error) {
|
||||||
|
var fileName string
|
||||||
|
if runtime.GOOS == "windows" {
|
||||||
|
fileName = "frpc.exe"
|
||||||
|
} else {
|
||||||
|
fileName = "frpc"
|
||||||
|
}
|
||||||
|
|
||||||
|
// 从 embed 读取
|
||||||
|
data, err := embeddedFrpc.ReadFile("bin/" + fileName)
|
||||||
|
if err != nil {
|
||||||
|
// 如果 embed 中没有对应文件,降级到系统 PATH 查找
|
||||||
|
path, err := exec.LookPath(fileName)
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("未找到 frpc 可执行文件(embed 和 PATH 均无): %w", err)
|
||||||
|
}
|
||||||
|
return path, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// 写入临时目录
|
||||||
|
tmpPath := os.TempDir() + "/frpc"
|
||||||
|
if runtime.GOOS == "windows" {
|
||||||
|
tmpPath += ".exe"
|
||||||
|
}
|
||||||
|
err = os.WriteFile(tmpPath, data, 0755)
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("写入临时 frpc 文件失败: %w", err)
|
||||||
|
}
|
||||||
|
return tmpPath, nil
|
||||||
|
}
|
||||||
|
|
||||||
// frpc.toml 模板 - 完全复制你的配置文件结构
|
// frpc.toml 模板 - 完全复制你的配置文件结构
|
||||||
const frpcTemplate = `serverAddr = "{{.ServerAddr}}"
|
const frpcTemplate = `serverAddr = "{{.ServerAddr}}"
|
||||||
serverPort = {{.ServerPort}}
|
serverPort = {{.ServerPort}}
|
||||||
@@ -37,15 +75,13 @@ localPort = {{.LocalPort}}
|
|||||||
remotePort = {{.RemotePort}}
|
remotePort = {{.RemotePort}}
|
||||||
{{end}}`
|
{{end}}`
|
||||||
|
|
||||||
// 生成 frpc.toml 文件
|
// GenerateFrpcConfig 生成 frpc.toml 配置文件
|
||||||
func GenerateFrpcConfig() error {
|
func GenerateFrpcConfig() error {
|
||||||
// 1. 读取全局配置
|
|
||||||
cfg, err := GetGlobalConfig()
|
cfg, err := GetGlobalConfig()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("读取全局配置失败: %w", err)
|
return fmt.Errorf("读取全局配置失败: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. 读取所有启用的隧道
|
|
||||||
proxies, err := GetProxies()
|
proxies, err := GetProxies()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("读取隧道列表失败: %w", err)
|
return fmt.Errorf("读取隧道列表失败: %w", err)
|
||||||
@@ -58,7 +94,6 @@ func GenerateFrpcConfig() error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3. 组合数据
|
|
||||||
data := struct {
|
data := struct {
|
||||||
*GlobalConfig
|
*GlobalConfig
|
||||||
Proxies []Proxy
|
Proxies []Proxy
|
||||||
@@ -67,7 +102,6 @@ func GenerateFrpcConfig() error {
|
|||||||
Proxies: activeProxies,
|
Proxies: activeProxies,
|
||||||
}
|
}
|
||||||
|
|
||||||
// 4. 渲染模板
|
|
||||||
tmpl, err := template.New("frpc").Parse(frpcTemplate)
|
tmpl, err := template.New("frpc").Parse(frpcTemplate)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("解析模板失败: %w", err)
|
return fmt.Errorf("解析模板失败: %w", err)
|
||||||
@@ -79,7 +113,6 @@ func GenerateFrpcConfig() error {
|
|||||||
return fmt.Errorf("渲染模板失败: %w", err)
|
return fmt.Errorf("渲染模板失败: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 5. 写入文件
|
|
||||||
err = os.WriteFile("./frpc.toml", buf.Bytes(), 0644)
|
err = os.WriteFile("./frpc.toml", buf.Bytes(), 0644)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("写入配置文件失败: %w", err)
|
return fmt.Errorf("写入配置文件失败: %w", err)
|
||||||
@@ -88,45 +121,76 @@ func GenerateFrpcConfig() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// 热加载 frpc
|
// StartFrpc 启动 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 {
|
func StartFrpc() error {
|
||||||
// 先确保配置文件存在
|
frpcPath, err := getFrpcPath()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("获取 frpc 路径失败: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查配置文件是否存在
|
||||||
if _, err := os.Stat("./frpc.toml"); os.IsNotExist(err) {
|
if _, err := os.Stat("./frpc.toml"); os.IsNotExist(err) {
|
||||||
if err := GenerateFrpcConfig(); err != nil {
|
if err := GenerateFrpcConfig(); err != nil {
|
||||||
return fmt.Errorf("生成配置文件失败: %w", err)
|
return fmt.Errorf("生成配置文件失败: %w", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd := exec.Command("frpc", "-c", "./frpc.toml")
|
// 先检查是否已在运行
|
||||||
// 后台运行,不阻塞
|
running, _ := GetFrpcStatus()
|
||||||
err := cmd.Start()
|
if running {
|
||||||
|
return nil // 已经在运行,不重复启动
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd := exec.Command(frpcPath, "-c", "./frpc.toml")
|
||||||
|
// Windows 下需要隐藏窗口(可选)
|
||||||
|
if runtime.GOOS == "windows" {
|
||||||
|
cmd.SysProcAttr = &syscall.SysProcAttr{HideWindow: true}
|
||||||
|
}
|
||||||
|
err = cmd.Start()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("启动 frpc 失败: %w", err)
|
return fmt.Errorf("启动 frpc 失败: %w", err)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ReloadFrpc 热加载 frpc 配置
|
||||||
|
func ReloadFrpc() error {
|
||||||
|
frpcPath, err := getFrpcPath()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("获取 frpc 路径失败: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查 frpc 是否在运行
|
||||||
|
running, err := GetFrpcStatus()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("检查 frpc 状态失败: %w", err)
|
||||||
|
}
|
||||||
|
if !running {
|
||||||
|
// 没运行就直接启动
|
||||||
|
return StartFrpc()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 执行 reload
|
||||||
|
cmd := exec.Command(frpcPath, "reload", "-c", "./frpc.toml")
|
||||||
|
output, err := cmd.CombinedOutput()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("reload 失败: %s, %w", string(output), err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// StopFrpc 停止 frpc
|
// StopFrpc 停止 frpc
|
||||||
func StopFrpc() error {
|
func StopFrpc() error {
|
||||||
|
if runtime.GOOS == "windows" {
|
||||||
|
// Windows 用 taskkill
|
||||||
|
cmd := exec.Command("taskkill", "/F", "/IM", "frpc.exe")
|
||||||
|
err := cmd.Run()
|
||||||
|
if err != nil && !strings.Contains(err.Error(), "not found") {
|
||||||
|
return fmt.Errorf("停止 frpc 失败: %w", err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
} else {
|
||||||
|
// Linux/Unix 用 pkill
|
||||||
cmd := exec.Command("pkill", "-f", "frpc")
|
cmd := exec.Command("pkill", "-f", "frpc")
|
||||||
err := cmd.Run()
|
err := cmd.Run()
|
||||||
if err != nil && !strings.Contains(err.Error(), "no process") {
|
if err != nil && !strings.Contains(err.Error(), "no process") {
|
||||||
@@ -134,9 +198,20 @@ func StopFrpc() error {
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 检查 frpc 状态
|
// GetFrpcStatus 检查 frpc 是否在运行
|
||||||
func GetFrpcStatus() (bool, error) {
|
func GetFrpcStatus() (bool, error) {
|
||||||
|
if runtime.GOOS == "windows" {
|
||||||
|
// Windows 用 tasklist 检查
|
||||||
|
cmd := exec.Command("tasklist", "/FI", "IMAGENAME eq frpc.exe")
|
||||||
|
output, err := cmd.CombinedOutput()
|
||||||
|
if err != nil {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
return strings.Contains(string(output), "frpc.exe"), nil
|
||||||
|
} else {
|
||||||
|
// Linux/Unix 用 pgrep
|
||||||
cmd := exec.Command("pgrep", "-f", "frpc")
|
cmd := exec.Command("pgrep", "-f", "frpc")
|
||||||
output, err := cmd.Output()
|
output, err := cmd.Output()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -144,3 +219,4 @@ func GetFrpcStatus() (bool, error) {
|
|||||||
}
|
}
|
||||||
return len(output) > 0, nil
|
return len(output) > 0, nil
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user