A privacy-first, self-hosted, fully open source personal knowledge management software, written in typescript and golang. (PERSONAL FORK)
at lambda-fork/main 139 lines 3.3 kB view raw
1// SiYuan - Refactor your thinking 2// Copyright (c) 2020-present, b3log.org 3// 4// This program is free software: you can redistribute it and/or modify 5// it under the terms of the GNU Affero General Public License as published by 6// the Free Software Foundation, either version 3 of the License, or 7// (at your option) any later version. 8// 9// This program is distributed in the hope that it will be useful, 10// but WITHOUT ANY WARRANTY; without even the implied warranty of 11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12// GNU Affero General Public License for more details. 13// 14// You should have received a copy of the GNU Affero General Public License 15// along with this program. If not, see <https://www.gnu.org/licenses/>. 16 17package server 18 19import ( 20 "fmt" 21 "os" 22 "os/exec" 23 "path/filepath" 24 "strconv" 25 "strings" 26 "time" 27 28 "github.com/88250/gulu" 29 goPS "github.com/mitchellh/go-ps" 30 "github.com/siyuan-note/logging" 31 "github.com/siyuan-note/siyuan/kernel/util" 32) 33 34func killRunningKernel() { 35 defer logging.Recover() 36 37 now := time.Now() 38 defer logging.LogInfof("check running kernel elapsed [%dms]", time.Since(now).Milliseconds()) 39 40 processes, err := goPS.Processes() 41 if err != nil { 42 logging.LogErrorf("get processes failed: %s", err) 43 killByPort(util.FixedPort) 44 return 45 } 46 47 currentPid := os.Getpid() 48 killed := false 49 for _, process := range processes { 50 if process.Pid() == currentPid { 51 continue 52 } 53 procName := strings.ToLower(process.Executable()) 54 if strings.Contains(procName, "siyuan-kernel") { 55 kill(fmt.Sprintf("%d", process.Pid())) 56 killed = true 57 } 58 } 59 60 if killed { 61 portJSON := filepath.Join(util.HomeDir, ".config", "siyuan", "port.json") 62 os.RemoveAll(portJSON) 63 } 64} 65 66func killByPort(port string) { 67 if !util.IsPortOpen(port) { 68 return 69 } 70 71 portJSON := filepath.Join(util.HomeDir, ".config", "siyuan", "port.json") 72 os.RemoveAll(portJSON) 73 74 pid := pidByPort(port) 75 if "" == pid { 76 return 77 } 78 79 pidInt, _ := strconv.Atoi(pid) 80 proc, _ := goPS.FindProcess(pidInt) 81 var name string 82 if nil != proc { 83 name = proc.Executable() 84 } 85 kill(pid) 86 logging.LogInfof("killed process [name=%s, pid=%s]", name, pid) 87} 88 89func kill(pid string) { 90 var killCmd *exec.Cmd 91 if gulu.OS.IsWindows() { 92 killCmd = exec.Command("cmd", "/c", "TASKKILL /F /PID "+pid) 93 } else { 94 killCmd = exec.Command("kill", "-9", pid) 95 } 96 gulu.CmdAttr(killCmd) 97 killCmd.CombinedOutput() 98} 99 100func pidByPort(port string) (ret string) { 101 if gulu.OS.IsWindows() { 102 cmd := exec.Command("cmd", "/c", "netstat -ano | findstr "+port) 103 gulu.CmdAttr(cmd) 104 data, err := cmd.CombinedOutput() 105 if err != nil { 106 logging.LogErrorf("netstat failed: %s", err) 107 return 108 } 109 output := string(data) 110 lines := strings.Split(output, "\n") 111 for _, l := range lines { 112 if strings.Contains(l, "LISTENING") { 113 l = l[strings.Index(l, "LISTENING")+len("LISTENING"):] 114 l = strings.TrimSpace(l) 115 ret = l 116 return 117 } 118 } 119 return 120 } 121 122 cmd := exec.Command("lsof", "-Fp", "-i", ":"+port) 123 gulu.CmdAttr(cmd) 124 data, err := cmd.CombinedOutput() 125 if err != nil { 126 logging.LogErrorf("lsof failed: %s", err) 127 return 128 } 129 output := string(data) 130 lines := strings.Split(output, "\n") 131 for _, l := range lines { 132 if strings.HasPrefix(l, "p") { 133 l = l[1:] 134 ret = l 135 return 136 } 137 } 138 return 139}