diff --git a/go.mod b/go.mod index 617dd77f..a86d2910 100644 --- a/go.mod +++ b/go.mod @@ -4,9 +4,12 @@ go 1.15 replace github.com/TeaOSLab/EdgeCommon => ../EdgeCommon +replace github.com/TeaOSLab/EdgePlus => ../EdgePlus + require ( github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d // indirect github.com/TeaOSLab/EdgeCommon v0.0.0-00010101000000-000000000000 + github.com/TeaOSLab/EdgePlus v0.0.0-00010101000000-000000000000 github.com/aliyun/alibaba-cloud-sdk-go v1.61.641 github.com/cespare/xxhash/v2 v2.1.1 github.com/go-acme/lego/v4 v4.1.2 @@ -15,6 +18,7 @@ require ( github.com/go-yaml/yaml v2.1.0+incompatible github.com/golang/protobuf v1.5.2 github.com/iwind/TeaGo v0.0.0-20210628135026-38575a4ab060 + github.com/iwind/gosock v0.0.0-20210722083328-12b2d66abec3 github.com/lionsoul2014/ip2region v2.2.0-release+incompatible github.com/mozillazg/go-pinyin v0.18.0 github.com/pkg/sftp v1.12.0 diff --git a/go.sum b/go.sum index 7bccbdc1..a07ba561 100644 --- a/go.sum +++ b/go.sum @@ -183,6 +183,8 @@ github.com/iij/doapi v0.0.0-20190504054126-0bbf12d6d7df/go.mod h1:QMZY7/J/KSQEhK github.com/iwind/TeaGo v0.0.0-20210411134150-ddf57e240c2f/go.mod h1:KU4mS7QNiZ7QWEuDBk1zw0/Q2LrAPZv3tycEFBsuUwc= github.com/iwind/TeaGo v0.0.0-20210628135026-38575a4ab060 h1:qdLtK4PDXxk2vMKkTWl5Fl9xqYuRCukzWAgJbLHdfOo= github.com/iwind/TeaGo v0.0.0-20210628135026-38575a4ab060/go.mod h1:KU4mS7QNiZ7QWEuDBk1zw0/Q2LrAPZv3tycEFBsuUwc= +github.com/iwind/gosock v0.0.0-20210722083328-12b2d66abec3 h1:aBSonas7vFcgTj9u96/bWGILGv1ZbUSTLiOzcI1ZT6c= +github.com/iwind/gosock v0.0.0-20210722083328-12b2d66abec3/go.mod h1:H5Q7SXwbx3a97ecJkaS2sD77gspzE7HFUafBO0peEyA= github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= github.com/jmespath/go-jmespath v0.3.0 h1:OS12ieG61fsCg5+qLJ+SsW9NicxNkg3b25OyT2yCeUc= github.com/jmespath/go-jmespath v0.3.0/go.mod h1:9QtRXoHjLGCJ5IBSaohpXITPlowMeeYCZ7fLUTSywik= diff --git a/internal/apps/app_cmd.go b/internal/apps/app_cmd.go index 7e671515..0624c20b 100644 --- a/internal/apps/app_cmd.go +++ b/internal/apps/app_cmd.go @@ -2,8 +2,11 @@ package apps import ( "fmt" - "github.com/iwind/TeaGo/Tea" + teaconst "github.com/TeaOSLab/EdgeAPI/internal/const" "github.com/iwind/TeaGo/logs" + "github.com/iwind/TeaGo/maps" + "github.com/iwind/TeaGo/types" + "github.com/iwind/gosock/pkg/gosock" "os" "os/exec" "runtime" @@ -11,7 +14,7 @@ import ( "time" ) -// App命令帮助 +// AppCmd App命令帮助 type AppCmd struct { product string version string @@ -20,10 +23,14 @@ type AppCmd struct { appendStrings []string directives []*Directive + + sock *gosock.Sock } func NewAppCmd() *AppCmd { - return &AppCmd{} + return &AppCmd{ + sock: gosock.NewTmpSock(teaconst.ProcessName), + } } type CommandHelpOption struct { @@ -31,25 +38,25 @@ type CommandHelpOption struct { Description string } -// 产品 +// Product 产品 func (this *AppCmd) Product(product string) *AppCmd { this.product = product return this } -// 版本 +// Version 版本 func (this *AppCmd) Version(version string) *AppCmd { this.version = version return this } -// 使用方法 +// Usage 使用方法 func (this *AppCmd) Usage(usage string) *AppCmd { this.usage = usage return this } -// 选项 +// Option 选项 func (this *AppCmd) Option(code string, description string) *AppCmd { this.options = append(this.options, &CommandHelpOption{ Code: code, @@ -58,13 +65,13 @@ func (this *AppCmd) Option(code string, description string) *AppCmd { return this } -// 附加内容 +// Append 附加内容 func (this *AppCmd) Append(appendString string) *AppCmd { this.appendStrings = append(this.appendStrings, appendString) return this } -// 打印 +// Print 打印 func (this *AppCmd) Print() { fmt.Println(this.product + " v" + this.version) @@ -103,7 +110,7 @@ func (this *AppCmd) Print() { } } -// 添加指令 +// On 添加指令 func (this *AppCmd) On(arg string, callback func()) { this.directives = append(this.directives, &Directive{ Arg: arg, @@ -111,7 +118,7 @@ func (this *AppCmd) On(arg string, callback func()) { }) } -// 运行 +// Run 运行 func (this *AppCmd) Run(main func()) { // 获取参数 args := os.Args[1:] @@ -150,9 +157,6 @@ func (this *AppCmd) Run(main func()) { return } - // 记录PID - _ = this.writePid() - // 日志 writer := new(LogWriter) writer.Init() @@ -164,7 +168,7 @@ func (this *AppCmd) Run(main func()) { // 版本号 func (this *AppCmd) runVersion() { - fmt.Println(this.product+" v"+this.version, "(build: "+runtime.Version(), runtime.GOOS, runtime.GOARCH+")") + fmt.Println(this.product+" v"+this.version, "(build: "+runtime.Version(), runtime.GOOS, runtime.GOARCH, teaconst.Tag+")") } // 帮助 @@ -174,9 +178,9 @@ func (this *AppCmd) runHelp() { // 启动 func (this *AppCmd) runStart() { - proc := this.checkPid() - if proc != nil { - fmt.Println(this.product+" already started, pid:", proc.Pid) + var pid = this.getPID() + if pid > 0 { + fmt.Println(this.product+" already started, pid:", pid) return } @@ -192,18 +196,15 @@ func (this *AppCmd) runStart() { // 停止 func (this *AppCmd) runStop() { - proc := this.checkPid() - if proc == nil { + var pid = this.getPID() + if pid == 0 { fmt.Println(this.product + " not started yet") return } - // 停止进程 - _ = proc.Kill() + _, _ = this.sock.Send(&gosock.Command{Code: "stop"}) - // 在Windows上经常不能及时释放资源 - _ = DeletePid(Tea.Root + "/bin/pid") - fmt.Println(this.product+" stopped ok, pid:", proc.Pid) + fmt.Println(this.product+" stopped ok, pid:", types.String(pid)) } // 重启 @@ -215,20 +216,24 @@ func (this *AppCmd) runRestart() { // 状态 func (this *AppCmd) runStatus() { - proc := this.checkPid() - if proc == nil { + var pid = this.getPID() + if pid == 0 { fmt.Println(this.product + " not started yet") - } else { - fmt.Println(this.product + " is running, pid: " + fmt.Sprintf("%d", proc.Pid)) + return } + + fmt.Println(this.product + " is running, pid: " + types.String(pid)) } -// 检查PID -func (this *AppCmd) checkPid() *os.Process { - return CheckPid(Tea.Root + "/bin/pid") -} +// 获取当前的PID +func (this *AppCmd) getPID() int { + if !this.sock.IsListening() { + return 0 + } -// 写入PID -func (this *AppCmd) writePid() error { - return WritePid(Tea.Root + "/bin/pid") + reply, err := this.sock.Send(&gosock.Command{Code: "pid"}) + if err != nil { + return 0 + } + return maps.NewMap(reply.Params).GetInt("pid") } diff --git a/internal/apps/file_others.go b/internal/apps/file_others.go deleted file mode 100644 index 73bf2fec..00000000 --- a/internal/apps/file_others.go +++ /dev/null @@ -1,17 +0,0 @@ -// +build !windows - -package apps - -import ( - "os" - "syscall" -) - -// lock file -func LockFile(fp *os.File) error { - return syscall.Flock(int(fp.Fd()), syscall.LOCK_EX|syscall.LOCK_NB) -} - -func UnlockFile(fp *os.File) error { - return syscall.Flock(int(fp.Fd()), syscall.LOCK_UN) -} diff --git a/internal/apps/file_windows.go b/internal/apps/file_windows.go deleted file mode 100644 index fa2028f2..00000000 --- a/internal/apps/file_windows.go +++ /dev/null @@ -1,17 +0,0 @@ -// +build windows - -package apps - -import ( - "errors" - "os" -) - -// lock file -func LockFile(fp *os.File) error { - return errors.New("not implemented on windows") -} - -func UnlockFile(fp *os.File) error { - return errors.New("not implemented on windows") -} diff --git a/internal/apps/pid.go b/internal/apps/pid.go deleted file mode 100644 index d5076ee3..00000000 --- a/internal/apps/pid.go +++ /dev/null @@ -1,113 +0,0 @@ -package apps - -import ( - "fmt" - "github.com/iwind/TeaGo/types" - "io/ioutil" - "os" - "runtime" -) - -var pidFileList = []*os.File{} - -// 检查Pid -func CheckPid(path string) *os.Process { - // windows上打开的文件是不能删除的 - if runtime.GOOS == "windows" { - if os.Remove(path) == nil { - return nil - } - } - - file, err := os.Open(path) - if err != nil { - return nil - } - - defer func() { - _ = file.Close() - }() - - // 是否能取得Lock - err = LockFile(file) - if err == nil { - _ = UnlockFile(file) - return nil - } - - pidBytes, err := ioutil.ReadAll(file) - if err != nil { - return nil - } - pid := types.Int(string(pidBytes)) - - if pid <= 0 { - return nil - } - - proc, _ := os.FindProcess(pid) - return proc -} - -// 写入Pid -func WritePid(path string) error { - fp, err := os.OpenFile(path, os.O_CREATE|os.O_TRUNC|os.O_WRONLY|os.O_RDONLY, 0666) - if err != nil { - return err - } - - if runtime.GOOS != "windows" { - err = LockFile(fp) - if err != nil { - return err - } - } - pidFileList = append(pidFileList, fp) // hold the file pointers - - _, err = fp.WriteString(fmt.Sprintf("%d", os.Getpid())) - if err != nil { - return err - } - - return nil -} - -// 写入Ppid -func WritePpid(path string) error { - fp, err := os.OpenFile(path, os.O_CREATE|os.O_TRUNC|os.O_WRONLY|os.O_RDONLY, 0666) - if err != nil { - return err - } - - if runtime.GOOS != "windows" { - err = LockFile(fp) - if err != nil { - return err - } - } - pidFileList = append(pidFileList, fp) // hold the file pointers - - _, err = fp.WriteString(fmt.Sprintf("%d", os.Getppid())) - if err != nil { - return err - } - - return nil -} - -// 删除Pid -func DeletePid(path string) error { - _, err := os.Stat(path) - if err != nil { - if !os.IsNotExist(err) { - return nil - } - return err - } - - for _, fp := range pidFileList { - _ = UnlockFile(fp) - _ = fp.Close() - } - return os.Remove(path) -} diff --git a/internal/const/build.go b/internal/const/build.go new file mode 100644 index 00000000..71c71807 --- /dev/null +++ b/internal/const/build.go @@ -0,0 +1,8 @@ +// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved. +// +build community + +package teaconst + +const BuildCommunity = true +const BuildPlus = false +const Tag = "community" diff --git a/internal/const/const.go b/internal/const/const.go index 5e0daa7d..81cc1551 100644 --- a/internal/const/const.go +++ b/internal/const/const.go @@ -22,5 +22,5 @@ const ( UserNodeVersion = "0.0.10" AuthorityNodeVersion = "0.0.2" MonitorNodeVersion = "0.0.2" - DNSNodeVersion = "0.0.2" + DNSNodeVersion = "0.0.3" ) diff --git a/internal/nodes/api_node.go b/internal/nodes/api_node.go index 2d5628f0..175d9987 100644 --- a/internal/nodes/api_node.go +++ b/internal/nodes/api_node.go @@ -16,8 +16,10 @@ import ( "github.com/iwind/TeaGo/dbs" "github.com/iwind/TeaGo/lists" "github.com/iwind/TeaGo/logs" + "github.com/iwind/TeaGo/maps" "github.com/iwind/TeaGo/types" stringutil "github.com/iwind/TeaGo/utils/string" + "github.com/iwind/gosock/pkg/gosock" "google.golang.org/grpc" "google.golang.org/grpc/credentials" "io/ioutil" @@ -36,11 +38,14 @@ var sharedAPIConfig *configs.APIConfig = nil type APINode struct { serviceInstanceMap map[string]interface{} serviceInstanceLocker sync.Mutex + + sock *gosock.Sock } func NewAPINode() *APINode { return &APINode{ serviceInstanceMap: map[string]interface{}{}, + sock: gosock.NewTmpSock(teaconst.ProcessName), } } @@ -469,37 +474,46 @@ func (this *APINode) listenPorts(apiNode *models.APINode) (isListening bool) { // 监听本地sock func (this *APINode) listenSock() error { - path := os.TempDir() + "/edge-api.sock" - - // 检查是否已经存在 - _, err := os.Stat(path) - if err == nil { - conn, err := net.Dial("unix", path) - if err != nil { - _ = os.Remove(path) + // 检查是否在运行 + if this.sock.IsListening() { + reply, err := this.sock.Send(&gosock.Command{Code: "pid"}) + if err == nil { + return errors.New("error: the process is already running, pid: " + maps.NewMap(reply.Params).GetString("pid")) } else { - _ = conn.Close() + return errors.New("error: the process is already running") } } - // 新的监听任务 - listener, err := net.Listen("unix", path) - if err != nil { - return err - } - events.On(events.EventQuit, func() { - remotelogs.Println("API_NODE", "quit unix sock") - _ = listener.Close() - }) - + // 启动监听 go func() { - for { - _, err := listener.Accept() - if err != nil { - return + this.sock.OnCommand(func(cmd *gosock.Command) { + switch cmd.Code { + case "pid": + _ = cmd.Reply(&gosock.Command{ + Code: "pid", + Params: map[string]interface{}{ + "pid": os.Getpid(), + }, + }) + case "stop": + _ = cmd.ReplyOk() + + // 退出主进程 + events.Notify(events.EventQuit) + os.Exit(0) } + }) + + err := this.sock.Listen() + if err != nil { + logs.Println("NODE", err.Error()) } }() + events.On(events.EventQuit, func() { + logs.Println("NODE", "quit unix sock") + _ = this.sock.Close() + }) + return nil }