diff --git a/kernel/server/port.go b/kernel/server/port.go new file mode 100644 index 000000000..d4814516d --- /dev/null +++ b/kernel/server/port.go @@ -0,0 +1,154 @@ +// SiYuan - Build Your Eternal Digital Garden +// Copyright (c) 2020-present, b3log.org +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +package server + +import ( + "fmt" + "net" + "os" + "os/exec" + "path/filepath" + "strconv" + "strings" + "time" + + "github.com/88250/gulu" + goPS "github.com/mitchellh/go-ps" + "github.com/siyuan-note/logging" + "github.com/siyuan-note/siyuan/kernel/util" +) + +func killRunningKernel() { + defer logging.Recover() + + if "dev" == util.Mode { + return + } + + if util.ContainerStd != util.Container { + return + } + + processes, err := goPS.Processes() + if nil != err { + logging.LogErrorf("get processes failed: %s", err) + killByPort(util.FixedPort) + return + } + + killed := false + for _, process := range processes { + procName := strings.ToLower(process.Executable()) + if strings.Contains(procName, "siyuan-kernel") { + kill(fmt.Sprintf("%d", process.Pid())) + killed = true + } + } + + if killed { + portJSON := filepath.Join(util.HomeDir, ".config", "siyuan", "port.json") + os.RemoveAll(portJSON) + } +} + +func killByPort(port string) { + if !isPortOpen(port) { + return + } + + portJSON := filepath.Join(util.HomeDir, ".config", "siyuan", "port.json") + os.RemoveAll(portJSON) + + pid := pidByPort(port) + if "" == pid { + return + } + + pidInt, _ := strconv.Atoi(pid) + proc, _ := goPS.FindProcess(pidInt) + var name string + if nil != proc { + name = proc.Executable() + } + kill(pid) + logging.LogInfof("killed process [name=%s, pid=%s]", name, pid) +} + +func isPortOpen(port string) bool { + timeout := time.Second + conn, err := net.DialTimeout("tcp", net.JoinHostPort("127.0.0.1", port), timeout) + if nil != err { + return false + } + if nil != conn { + conn.Close() + return true + } + return false +} + +func kill(pid string) { + var killCmd *exec.Cmd + if gulu.OS.IsWindows() { + killCmd = exec.Command("cmd", "/c", "TASKKILL /F /PID "+pid) + } else { + killCmd = exec.Command("kill", "-9", pid) + } + gulu.CmdAttr(killCmd) + killCmd.CombinedOutput() +} + +func pidByPort(port string) (ret string) { + if gulu.OS.IsWindows() { + cmd := exec.Command("cmd", "/c", "netstat -ano | findstr "+port) + gulu.CmdAttr(cmd) + data, err := cmd.CombinedOutput() + if nil != err { + logging.LogErrorf("netstat failed: %s", err) + return + } + output := string(data) + lines := strings.Split(output, "\n") + for _, l := range lines { + if strings.Contains(l, "LISTENING") { + l = l[strings.Index(l, "LISTENING")+len("LISTENING"):] + l = strings.TrimSpace(l) + ret = l + return + } + } + return + } + + cmd := exec.Command("lsof", "-Fp", "-i", ":"+port) + gulu.CmdAttr(cmd) + data, err := cmd.CombinedOutput() + if nil != err { + logging.LogErrorf("lsof failed: %s", err) + return + } + output := string(data) + lines := strings.Split(output, "\n") + for _, l := range lines { + if strings.HasPrefix(l, "p") { + l = l[1:] + ret = l + return + } + } + return +} diff --git a/kernel/server/serve.go b/kernel/server/serve.go index eb88e50a6..941517f9f 100644 --- a/kernel/server/serve.go +++ b/kernel/server/serve.go @@ -24,10 +24,8 @@ import ( "net/http/pprof" "net/url" "os" - "os/exec" "path" "path/filepath" - "strconv" "strings" "time" @@ -36,7 +34,6 @@ import ( "github.com/gin-contrib/sessions" "github.com/gin-contrib/sessions/cookie" "github.com/gin-gonic/gin" - goPS "github.com/mitchellh/go-ps" "github.com/mssola/user_agent" "github.com/olahol/melody" "github.com/siyuan-note/logging" @@ -458,124 +455,3 @@ func corsMiddleware() gin.HandlerFunc { c.Next() } } - -func killRunningKernel() { - defer logging.Recover() - - if "dev" == util.Mode { - return - } - - if util.ContainerStd != util.Container { - return - } - - processes, err := goPS.Processes() - if nil != err { - logging.LogErrorf("get processes failed: %s", err) - killByPort(util.FixedPort) - return - } - - killed := false - for _, process := range processes { - procName := strings.ToLower(process.Executable()) - if strings.Contains(procName, "siyuan-kernel") { - kill(fmt.Sprintf("%d", process.Pid())) - killed = true - } - } - - if killed { - portJSON := filepath.Join(util.HomeDir, ".config", "siyuan", "port.json") - os.RemoveAll(portJSON) - } -} - -func killByPort(port string) { - if !isPortOpen(port) { - return - } - - portJSON := filepath.Join(util.HomeDir, ".config", "siyuan", "port.json") - os.RemoveAll(portJSON) - - pid := pidByPort(port) - if "" == pid { - return - } - - pidInt, _ := strconv.Atoi(pid) - proc, _ := goPS.FindProcess(pidInt) - var name string - if nil != proc { - name = proc.Executable() - } - kill(pid) - logging.LogInfof("killed process [name=%s, pid=%s]", name, pid) -} - -func isPortOpen(port string) bool { - timeout := time.Second - conn, err := net.DialTimeout("tcp", net.JoinHostPort("127.0.0.1", port), timeout) - if nil != err { - return false - } - if nil != conn { - conn.Close() - return true - } - return false -} - -func kill(pid string) { - var killCmd *exec.Cmd - if gulu.OS.IsWindows() { - killCmd = exec.Command("cmd", "/c", "TASKKILL /F /PID "+pid) - } else { - killCmd = exec.Command("kill", "-9", pid) - } - gulu.CmdAttr(killCmd) - killCmd.CombinedOutput() -} - -func pidByPort(port string) (ret string) { - if gulu.OS.IsWindows() { - cmd := exec.Command("cmd", "/c", "netstat -ano | findstr "+port) - gulu.CmdAttr(cmd) - data, err := cmd.CombinedOutput() - if nil != err { - logging.LogErrorf("netstat failed: %s", err) - return - } - output := string(data) - lines := strings.Split(output, "\n") - for _, l := range lines { - if strings.Contains(l, "LISTENING") { - l = l[strings.Index(l, "LISTENING")+len("LISTENING"):] - l = strings.TrimSpace(l) - ret = l - return - } - } - return - } - - cmd := exec.Command("lsof", "-Fp", "-i", ":"+port) - gulu.CmdAttr(cmd) - data, err := cmd.CombinedOutput() - if nil != err { - logging.LogErrorf("lsof failed: %s", err) - return - } - output := string(data) - lines := strings.Split(output, "\n") - for _, l := range lines { - if strings.HasPrefix(l, "p") { - l = l[1:] - ret = l - return - } - } - return -}