diff --git a/bin/frpc_windows_amd64.exe b/bin/frpc_windows_amd64.exe deleted file mode 100644 index e8b0189..0000000 Binary files a/bin/frpc_windows_amd64.exe and /dev/null differ diff --git a/go.mod b/go.mod index a17a9cb..3592153 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,7 @@ require ( github.com/golang-jwt/jwt/v5 v5.3.1 golang.org/x/crypto v0.54.0 golang.org/x/sys v0.47.0 - modernc.org/sqlite v1.54.0 + modernc.org/sqlite v1.29.9 ) require ( @@ -24,16 +24,17 @@ require ( github.com/goccy/go-json v0.10.5 // indirect github.com/goccy/go-yaml v1.19.2 // indirect github.com/google/uuid v1.6.0 // indirect + github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect github.com/json-iterator/go v1.1.12 // indirect github.com/klauspost/cpuid/v2 v2.3.0 // indirect github.com/leodido/go-urn v1.4.0 // indirect github.com/mattn/go-isatty v0.0.20 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect - github.com/ncruces/go-strftime v1.0.0 // indirect + github.com/ncruces/go-strftime v0.1.9 // indirect github.com/pelletier/go-toml/v2 v2.2.4 // indirect github.com/quic-go/qpack v0.6.0 // indirect - github.com/quic-go/quic-go v0.59.0 // indirect + github.com/quic-go/quic-go v0.59.1 // indirect github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect github.com/twitchyliquid64/golang-asm v0.15.1 // indirect github.com/ugorji/go/codec v1.3.1 // indirect @@ -42,7 +43,10 @@ require ( golang.org/x/net v0.56.0 // indirect golang.org/x/text v0.40.0 // indirect google.golang.org/protobuf v1.36.10 // indirect - modernc.org/libc v1.74.1 // indirect - modernc.org/mathutil v1.7.1 // indirect - modernc.org/memory v1.11.0 // indirect + modernc.org/gc/v3 v3.0.0-20240107210532-573471604cb6 // indirect + modernc.org/libc v1.49.3 // indirect + modernc.org/mathutil v1.6.0 // indirect + modernc.org/memory v1.8.0 // indirect + modernc.org/strutil v1.2.0 // indirect + modernc.org/token v1.1.0 // indirect ) diff --git a/go.sum b/go.sum index 935b577..ef5afd9 100644 --- a/go.sum +++ b/go.sum @@ -34,8 +34,8 @@ github.com/golang-jwt/jwt/v5 v5.3.1/go.mod h1:fxCRLWMO43lRc8nhHWY6LGqRcf+1gQWArs github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e h1:ijClszYn+mADRFY17kjQEVQ1XRhq2/JR1M3sGqeJoxs= -github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e/go.mod h1:boTsfXsheKC2y+lKOCMpSfarhxDeIzfZG1jqGcPl3cA= +github.com/google/pprof v0.0.0-20240409012703-83162a5b38cd h1:gbpYu9NMq8jhDVbvlGkMFWCjLFlqqEZjEmObmhUy6Vo= +github.com/google/pprof v0.0.0-20240409012703-83162a5b38cd/go.mod h1:kf6iHlnVGwgKolg33glAes7Yg/8iWP8ukqeldJSO7jw= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k= @@ -53,16 +53,16 @@ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= -github.com/ncruces/go-strftime v1.0.0 h1:HMFp8mLCTPp341M/ZnA4qaf7ZlsbTc+miZjCLOFAw7w= -github.com/ncruces/go-strftime v1.0.0/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls= +github.com/ncruces/go-strftime v0.1.9 h1:bY0MQC28UADQmHmaF5dgpLmImcShSi2kHU9XLdhx/f4= +github.com/ncruces/go-strftime v0.1.9/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls= github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4= github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/quic-go/qpack v0.6.0 h1:g7W+BMYynC1LbYLSqRt8PBg5Tgwxn214ZZR34VIOjz8= github.com/quic-go/qpack v0.6.0/go.mod h1:lUpLKChi8njB4ty2bFLX2x4gzDqXwUpaO1DP9qMDZII= -github.com/quic-go/quic-go v0.59.0 h1:OLJkp1Mlm/aS7dpKgTc6cnpynnD2Xg7C1pwL6vy/SAw= -github.com/quic-go/quic-go v0.59.0/go.mod h1:upnsH4Ju1YkqpLXC305eW3yDZ4NfnNbmQRCMWS58IKU= +github.com/quic-go/quic-go v0.59.1 h1:0Gmua0HW1Tv7ANR7hUYwRyD0MG5OJfgvYSZasGZzBic= +github.com/quic-go/quic-go v0.59.1/go.mod h1:upnsH4Ju1YkqpLXC305eW3yDZ4NfnNbmQRCMWS58IKU= github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE= github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= @@ -107,31 +107,29 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -modernc.org/cc/v4 v4.29.0 h1:CXgwL8cvxmyzBQZzbSl/6xFtMCryb6u8IOqDci39cgc= -modernc.org/cc/v4 v4.29.0/go.mod h1:OnovgIhbbMXMu1aISnJ0wvVD1KnW+cAUJkIrAWh+kVI= -modernc.org/ccgo/v4 v4.34.6 h1:sBgfIwyN0TQ9C5hwIeuqyeAKyMWnbvj2fvpF4L11uzU= -modernc.org/ccgo/v4 v4.34.6/go.mod h1:SZ8YcN9NG7XVsQYdm6jYBvi8PQP1qi+kqB6OhjqI3Fk= -modernc.org/fileutil v1.4.0 h1:j6ZzNTftVS054gi281TyLjHPp6CPHr2KCxEXjEbD6SM= -modernc.org/fileutil v1.4.0/go.mod h1:EqdKFDxiByqxLk8ozOxObDSfcVOv/54xDs/DUHdvCUU= -modernc.org/gc/v2 v2.6.5 h1:nyqdV8q46KvTpZlsw66kWqwXRHdjIlJOhG6kxiV/9xI= -modernc.org/gc/v2 v2.6.5/go.mod h1:YgIahr1ypgfe7chRuJi2gD7DBQiKSLMPgBQe9oIiito= -modernc.org/gc/v3 v3.1.4 h1:2g65LGVSmFQrXeITAw97x7hCRvZFcyE1uDP+7Vng7JI= -modernc.org/gc/v3 v3.1.4/go.mod h1:HFK/6AGESC7Ex+EZJhJ2Gni6cTaYpSMmU/cT9RmlfYY= -modernc.org/goabi0 v0.2.0 h1:HvEowk7LxcPd0eq6mVOAEMai46V+i7Jrj13t4AzuNks= -modernc.org/goabi0 v0.2.0/go.mod h1:CEFRnnJhKvWT1c1JTI3Avm+tgOWbkOu5oPA8eH8LnMI= -modernc.org/libc v1.74.1 h1:bdR4VTKFMC4966QSNZ05XLGI/VwzVa2kTUX51Dm0riQ= -modernc.org/libc v1.74.1/go.mod h1:uH4t5bOx3G3g9Xcmj10YKlTcVISlRDwv8VoQJG9n8Os= -modernc.org/mathutil v1.7.1 h1:GCZVGXdaN8gTqB1Mf/usp1Y/hSqgI2vAGGP4jZMCxOU= -modernc.org/mathutil v1.7.1/go.mod h1:4p5IwJITfppl0G4sUEDtCr4DthTaT47/N3aT6MhfgJg= -modernc.org/memory v1.11.0 h1:o4QC8aMQzmcwCK3t3Ux/ZHmwFPzE6hf2Y5LbkRs+hbI= -modernc.org/memory v1.11.0/go.mod h1:/JP4VbVC+K5sU2wZi9bHoq2MAkCnrt2r98UGeSK7Mjw= -modernc.org/opt v0.2.0 h1:tGyef5ApycA7FSEOMraay9SaTk5zmbx7Tu+cJs4QKZg= -modernc.org/opt v0.2.0/go.mod h1:03fq9lsNfvkYSfxrfUhZCWPk1lm4cq4N+Bh//bEtgns= -modernc.org/sortutil v1.2.1 h1:+xyoGf15mM3NMlPDnFqrteY07klSFxLElE2PVuWIJ7w= -modernc.org/sortutil v1.2.1/go.mod h1:7ZI3a3REbai7gzCLcotuw9AC4VZVpYMjDzETGsSMqJE= -modernc.org/sqlite v1.54.0 h1:JCxR4qwkJvOaqAoYcgDoO25Nc+ROg6EJ2LfBVzdrgog= -modernc.org/sqlite v1.54.0/go.mod h1:4ntCLuNmnH8+GNqjka1wNg7KJd5/Hi5FYp8K+XQ7GZw= -modernc.org/strutil v1.2.1 h1:UneZBkQA+DX2Rp35KcM69cSsNES9ly8mQWD71HKlOA0= -modernc.org/strutil v1.2.1/go.mod h1:EHkiggD70koQxjVdSBM3JKM7k6L0FbGE5eymy9i3B9A= +modernc.org/cc/v4 v4.20.0 h1:45Or8mQfbUqJOG9WaxvlFYOAQO0lQ5RvqBcFCXngjxk= +modernc.org/cc/v4 v4.20.0/go.mod h1:HM7VJTZbUCR3rV8EYBi9wxnJ0ZBRiGE5OeGXNA0IsLQ= +modernc.org/ccgo/v4 v4.16.0 h1:ofwORa6vx2FMm0916/CkZjpFPSR70VwTjUCe2Eg5BnA= +modernc.org/ccgo/v4 v4.16.0/go.mod h1:dkNyWIjFrVIZ68DTo36vHK+6/ShBn4ysU61So6PIqCI= +modernc.org/fileutil v1.3.0 h1:gQ5SIzK3H9kdfai/5x41oQiKValumqNTDXMvKo62HvE= +modernc.org/fileutil v1.3.0/go.mod h1:XatxS8fZi3pS8/hKG2GH/ArUogfxjpEKs3Ku3aK4JyQ= +modernc.org/gc/v2 v2.4.1 h1:9cNzOqPyMJBvrUipmynX0ZohMhcxPtMccYgGOJdOiBw= +modernc.org/gc/v2 v2.4.1/go.mod h1:wzN5dK1AzVGoH6XOzc3YZ+ey/jPgYHLuVckd62P0GYU= +modernc.org/gc/v3 v3.0.0-20240107210532-573471604cb6 h1:5D53IMaUuA5InSeMu9eJtlQXS2NxAhyWQvkKEgXZhHI= +modernc.org/gc/v3 v3.0.0-20240107210532-573471604cb6/go.mod h1:Qz0X07sNOR1jWYCrJMEnbW/X55x206Q7Vt4mz6/wHp4= +modernc.org/libc v1.49.3 h1:j2MRCRdwJI2ls/sGbeSk0t2bypOG/uvPZUsGQFDulqg= +modernc.org/libc v1.49.3/go.mod h1:yMZuGkn7pXbKfoT/M35gFJOAEdSKdxL0q64sF7KqCDo= +modernc.org/mathutil v1.6.0 h1:fRe9+AmYlaej+64JsEEhoWuAYBkOtQiMEU7n/XgfYi4= +modernc.org/mathutil v1.6.0/go.mod h1:Ui5Q9q1TR2gFm0AQRqQUaBWFLAhQpCwNcuhBOSedWPo= +modernc.org/memory v1.8.0 h1:IqGTL6eFMaDZZhEWwcREgeMXYwmW83LYW8cROZYkg+E= +modernc.org/memory v1.8.0/go.mod h1:XPZ936zp5OMKGWPqbD3JShgd/ZoQ7899TUuQqxY+peU= +modernc.org/opt v0.1.3 h1:3XOZf2yznlhC+ibLltsDGzABUGVx8J6pnFMS3E4dcq4= +modernc.org/opt v0.1.3/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0= +modernc.org/sortutil v1.2.0 h1:jQiD3PfS2REGJNzNCMMaLSp/wdMNieTbKX920Cqdgqc= +modernc.org/sortutil v1.2.0/go.mod h1:TKU2s7kJMf1AE84OoiGppNHJwvB753OYfNl2WRb++Ss= +modernc.org/sqlite v1.29.9 h1:9RhNMklxJs+1596GNuAX+O/6040bvOwacTxuFcRuQow= +modernc.org/sqlite v1.29.9/go.mod h1:ItX2a1OVGgNsFh6Dv60JQvGfJfTPHPVpV6DF59akYOA= +modernc.org/strutil v1.2.0 h1:agBi9dp1I+eOnxXeiZawM8F4LawKv4NzGWSaLfyeNZA= +modernc.org/strutil v1.2.0/go.mod h1:/mdcBmfOibveCTBxUl5B5l6W+TTH1FXPLHZE6bTosX0= modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y= modernc.org/token v1.1.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM= diff --git a/internal/api/handler.go b/internal/api/handler.go index c3572e2..b348c29 100644 --- a/internal/api/handler.go +++ b/internal/api/handler.go @@ -1,6 +1,9 @@ package api import ( + "bytes" + "fmt" + "html/template" "net" "net/http" "strconv" @@ -415,3 +418,125 @@ func readTailLog(filePath string, n int) ([]string, error) { // 为了编译通过,先简单返回空 return []string{}, nil } + +// ================================================================ +// 导入/导出 TOML +// ================================================================ + +func ImportTomlHandler(c *gin.Context) { + file, err := c.FormFile("file") + if err != nil { + c.JSON(http.StatusBadRequest, gin.H{"code": 1, "msg": "请选择文件"}) + return + } + + f, err := file.Open() + if err != nil { + c.JSON(http.StatusInternalServerError, gin.H{"code": 2, "msg": "读取文件失败"}) + return + } + defer f.Close() + + buf := new(bytes.Buffer) + if _, err := buf.ReadFrom(f); err != nil { + c.JSON(http.StatusInternalServerError, gin.H{"code": 2, "msg": "读取文件失败"}) + return + } + + parsed, err := frp.ParseToml(buf.String()) + if err != nil { + c.JSON(http.StatusBadRequest, gin.H{"code": 1, "msg": "解析 TOML 失败: " + err.Error()}) + return + } + + cfg := parsed.ToGlobalConfig() + cfg.TcpMux = true + if err := db.UpdateGlobalConfig(cfg); err != nil { + c.JSON(http.StatusInternalServerError, gin.H{"code": 2, "msg": "更新配置失败: " + err.Error()}) + return + } + + if _, err := db.DB.Exec("DELETE FROM proxies"); err != nil { + c.JSON(http.StatusInternalServerError, gin.H{"code": 2, "msg": "清空隧道失败"}) + return + } + + proxies := parsed.ToProxies() + for _, p := range proxies { + if err := db.CreateProxy(&p); err != nil { + c.JSON(http.StatusInternalServerError, gin.H{"code": 2, "msg": "导入隧道失败: " + err.Error()}) + return + } + } + + if err := frp.GenerateConfig(); err != nil { + c.JSON(http.StatusInternalServerError, gin.H{"code": 2, "msg": "生成配置失败: " + err.Error()}) + return + } + + if err := frp.Reload(); err != nil { + c.JSON(http.StatusOK, gin.H{ + "code": 0, + "msg": fmt.Sprintf("导入成功!共 %d 条隧道,但热加载失败: %s", len(proxies), err.Error()), + }) + return + } + + c.JSON(http.StatusOK, gin.H{ + "code": 0, + "msg": fmt.Sprintf("导入成功!共 %d 条隧道", len(proxies)), + }) +} + +func ExportTomlHandler(c *gin.Context) { + cfg, err := db.GetGlobalConfig() + if err != nil { + c.JSON(http.StatusInternalServerError, gin.H{"code": 2, "msg": "读取配置失败: " + err.Error()}) + return + } + + proxies, err := db.GetProxies() + if err != nil { + c.JSON(http.StatusInternalServerError, gin.H{"code": 2, "msg": "读取隧道失败: " + err.Error()}) + return + } + + var activeProxies []db.Proxy + for _, p := range proxies { + if p.Enabled { + activeProxies = append(activeProxies, p) + } + } + + data := struct { + *db.GlobalConfig + Proxies []db.Proxy + WireProtocolLine string + }{ + GlobalConfig: cfg, + Proxies: activeProxies, + } + + if cfg.WireProtocolV2 { + data.WireProtocolLine = `wireProtocol = "v2"` + } else { + data.WireProtocolLine = "" + } + + // 这里需要 frp.FrpcTemplateContent,需要从 frp 包导出 + tmpl, err := template.New("frpc").Parse(frp.FrpcTemplateContent) + if err != nil { + c.JSON(http.StatusInternalServerError, gin.H{"code": 2, "msg": "解析模板失败: " + err.Error()}) + return + } + + var buf bytes.Buffer + if err := tmpl.Execute(&buf, data); err != nil { + c.JSON(http.StatusInternalServerError, gin.H{"code": 2, "msg": "渲染模板失败: " + err.Error()}) + return + } + + c.Header("Content-Type", "text/plain; charset=utf-8") + c.Header("Content-Disposition", "attachment; filename=frpc.toml") + c.String(http.StatusOK, buf.String()) +} diff --git a/static/app.js b/internal/api/static/app.js similarity index 100% rename from static/app.js rename to internal/api/static/app.js diff --git a/static/fonts/HarmonyOS_Sans_SC_Regular.ttf b/internal/api/static/fonts/HarmonyOS_Sans_SC_Regular.ttf similarity index 100% rename from static/fonts/HarmonyOS_Sans_SC_Regular.ttf rename to internal/api/static/fonts/HarmonyOS_Sans_SC_Regular.ttf diff --git a/static/index.html b/internal/api/static/index.html similarity index 100% rename from static/index.html rename to internal/api/static/index.html diff --git a/static/logo.svg b/internal/api/static/logo.svg similarity index 100% rename from static/logo.svg rename to internal/api/static/logo.svg diff --git a/static/style-1.css b/internal/api/static/style-1.css similarity index 100% rename from static/style-1.css rename to internal/api/static/style-1.css diff --git a/static/style-2.css b/internal/api/static/style-2.css similarity index 100% rename from static/style-2.css rename to internal/api/static/style-2.css diff --git a/static/style-3.css b/internal/api/static/style-3.css similarity index 100% rename from static/style-3.css rename to internal/api/static/style-3.css diff --git a/static/style-4.css b/internal/api/static/style-4.css similarity index 100% rename from static/style-4.css rename to internal/api/static/style-4.css diff --git a/bin/frpc_linux_amd64 b/internal/frp/bin/frpc_linux_amd64 similarity index 100% rename from bin/frpc_linux_amd64 rename to internal/frp/bin/frpc_linux_amd64 diff --git a/bin/frpc_linux_arm64 b/internal/frp/bin/frpc_linux_arm64 similarity index 100% rename from bin/frpc_linux_arm64 rename to internal/frp/bin/frpc_linux_arm64 diff --git a/bin/frpc_linux_arm_hf b/internal/frp/bin/frpc_linux_arm_hf similarity index 100% rename from bin/frpc_linux_arm_hf rename to internal/frp/bin/frpc_linux_arm_hf diff --git a/internal/frp/config.go b/internal/frp/config.go index 64d79d9..a9680c1 100644 --- a/internal/frp/config.go +++ b/internal/frp/config.go @@ -2,6 +2,7 @@ package frp import ( "bytes" + _ "embed" "os" "text/template" diff --git a/frpc.tmpl b/internal/frp/frpc.tmpl similarity index 100% rename from frpc.tmpl rename to internal/frp/frpc.tmpl diff --git a/internal/process/attr_other.go b/internal/process/attr_other.go index d93b17d..6ca9d61 100644 --- a/internal/process/attr_other.go +++ b/internal/process/attr_other.go @@ -1,19 +1,12 @@ -//go:build !linux +//go:build !linux && !windows package process import ( "os/exec" - "runtime" - "syscall" ) -// setProcessAttributes 设置进程属性 (非 Linux) +// setProcessAttributes 其他平台(macOS/FreeBSD 等)不做特殊设置 func setProcessAttributes(cmd *exec.Cmd) { - if runtime.GOOS == "windows" { - cmd.SysProcAttr = &syscall.SysProcAttr{ - HideWindow: true, - } - } - // 其他平台不做特殊设置 + // 其他平台不需要特殊设置 } diff --git a/internal/process/attr_windows.go b/internal/process/attr_windows.go new file mode 100644 index 0000000..7e10535 --- /dev/null +++ b/internal/process/attr_windows.go @@ -0,0 +1,14 @@ +//go:build windows + +package process + +import ( + "os/exec" + "syscall" +) + +func setProcessAttributes(cmd *exec.Cmd) { + cmd.SysProcAttr = &syscall.SysProcAttr{ + HideWindow: true, + } +} diff --git a/main.go b/main.go index f5e7afe..057f305 100644 --- a/main.go +++ b/main.go @@ -16,16 +16,10 @@ import ( func main() { log.SetFlags(log.LstdFlags | log.Lshortfile) - // ============================================================ - // 1. 初始化数据目录 - // ============================================================ if err := os.MkdirAll("./data", 0755); err != nil { log.Printf("⚠️ 创建 data 目录失败: %v", err) } - // ============================================================ - // 2. 显示版本信息 - // ============================================================ if data, err := os.ReadFile("./data/version.ini"); err == nil { version := strings.TrimSpace(string(data)) log.Printf("📌 版本: %s", version) @@ -33,34 +27,23 @@ func main() { log.Printf("📌 版本: (未记录)") } - // ============================================================ - // 3. 初始化数据库 - // ============================================================ if err := db.InitDB(); err != nil { log.Fatal("❌ 数据库初始化失败:", err) } - // ============================================================ - // 4. 生成 frpc 配置文件 - // ============================================================ if err := frp.GenerateConfig(); err != nil { log.Println("⚠️ 生成配置文件失败:", err) } - // ============================================================ - // 5. 创建进程管理器并启动 frpc - // ============================================================ - pm := process.NewManager("./data", "./data/frpc.toml") + pm := process.NewManager("./data", "./data/frpc.toml", "./data/frpc") process.SetGlobalManager(pm) - // 加载 admin_port 配置 if err := pm.LoadConfig(); err != nil { log.Printf("⚠️ 加载 admin_port 配置失败: %v (将使用 PID 文件模式)", err) } else { log.Printf("📌 admin_port: %d", pm.AdminPort()) } - // 启动 frpc (幂等) ctx := context.Background() if err := pm.Start(ctx); err != nil { log.Printf("⚠️ 启动 frpc 失败: %v", err) @@ -73,14 +56,8 @@ func main() { } } - // ============================================================ - // 6. 启动看门狗 (自动恢复) - // ============================================================ go startWatchdog(pm) - // ============================================================ - // 7. 启动 HTTP 服务 - // ============================================================ router := api.SetupRouter() log.Println("🚀 frpc-console 启动成功!") log.Println("📍 访问地址: http://localhost:9300") @@ -91,11 +68,7 @@ func main() { } } -// ================================================================ -// 看门狗 -// ================================================================ - -func startWatchdog(pm *process.Manager) { +func startWatchdog(pm *process.ProcessManager) { ticker := time.NewTicker(30 * time.Second) defer ticker.Stop()