99 lines
2.2 KiB
Go
99 lines
2.2 KiB
Go
package frp
|
|
|
|
import (
|
|
"embed"
|
|
"fmt"
|
|
"os"
|
|
"os/exec"
|
|
"path/filepath"
|
|
"runtime"
|
|
"sync"
|
|
)
|
|
|
|
//go:embed bin/*
|
|
var embeddedFrpc embed.FS
|
|
|
|
var (
|
|
cachedFrpcPath string
|
|
frpcPathMutex sync.Mutex
|
|
)
|
|
|
|
// GetFrpcPath 获取 frpc 二进制路径
|
|
// 优先级: 本地缓存 > 程序同目录 > 当前工作目录 > embed 提取到当前目录 > 系统 PATH
|
|
func GetFrpcPath() (string, error) {
|
|
frpcPathMutex.Lock()
|
|
defer frpcPathMutex.Unlock()
|
|
|
|
if cachedFrpcPath != "" {
|
|
if _, err := os.Stat(cachedFrpcPath); err == nil {
|
|
return cachedFrpcPath, nil
|
|
}
|
|
cachedFrpcPath = ""
|
|
}
|
|
|
|
var fileName string
|
|
switch {
|
|
case runtime.GOOS == "windows" && runtime.GOARCH == "amd64":
|
|
fileName = "frpc_windows_amd64.exe"
|
|
case runtime.GOOS == "linux" && runtime.GOARCH == "amd64":
|
|
fileName = "frpc_linux_amd64"
|
|
case runtime.GOOS == "linux" && runtime.GOARCH == "arm64":
|
|
fileName = "frpc_linux_arm64"
|
|
case runtime.GOOS == "linux" && runtime.GOARCH == "arm":
|
|
fileName = "frpc_linux_arm_hf"
|
|
default:
|
|
path, err := exec.LookPath("frpc")
|
|
if err == nil {
|
|
cachedFrpcPath = path
|
|
return path, nil
|
|
}
|
|
return "", fmt.Errorf("不支持的平台: %s/%s", runtime.GOOS, runtime.GOARCH)
|
|
}
|
|
|
|
// 方法1: 尝试从程序同目录加载
|
|
execPath, err := os.Executable()
|
|
if err == nil {
|
|
execDir := filepath.Dir(execPath)
|
|
localPath := filepath.Join(execDir, "frpc")
|
|
if runtime.GOOS == "windows" {
|
|
localPath += ".exe"
|
|
}
|
|
if _, err := os.Stat(localPath); err == nil {
|
|
cachedFrpcPath = localPath
|
|
return localPath, nil
|
|
}
|
|
}
|
|
|
|
// 方法2: 尝试从当前工作目录加载
|
|
cwdPath := "./frpc"
|
|
if runtime.GOOS == "windows" {
|
|
cwdPath += ".exe"
|
|
}
|
|
if _, err := os.Stat(cwdPath); err == nil {
|
|
cachedFrpcPath = cwdPath
|
|
return cwdPath, nil
|
|
}
|
|
|
|
// 方法3: 从 embed 提取到当前工作目录
|
|
data, err := embeddedFrpc.ReadFile("bin/" + fileName)
|
|
if err == nil {
|
|
extractPath := "./frpc"
|
|
if runtime.GOOS == "windows" {
|
|
extractPath += ".exe"
|
|
}
|
|
if err := os.WriteFile(extractPath, data, 0755); err == nil {
|
|
cachedFrpcPath = extractPath
|
|
return extractPath, nil
|
|
}
|
|
}
|
|
|
|
// 方法4: 从系统 PATH 查找
|
|
path, err := exec.LookPath("frpc")
|
|
if err == nil {
|
|
cachedFrpcPath = path
|
|
return path, nil
|
|
}
|
|
|
|
return "", fmt.Errorf("未找到 frpc 文件")
|
|
}
|