Skip to content

Commit 3029ca0

Browse files
authored
Merge pull request #17 from Karmenzind/dev
Dev
2 parents 1f59eff + fc81aac commit 3029ca0

File tree

7 files changed

+149
-80
lines changed

7 files changed

+149
-80
lines changed

README.md

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
**TOC**
1212
<!-- vim-markdown-toc GitLab -->
1313

14-
* [☑️ 特性](#-特性)
14+
* [:ballot_box_with_check: 特性](#ballot_box_with_check-特性)
1515
* [🚀 安装和升级](#-安装和升级)
1616
* [Linux/MacOS](#linuxmacos)
1717
* [ArchLinux](#archlinux)
@@ -28,8 +28,7 @@
2828

2929
<!-- vim-markdown-toc -->
3030

31-
32-
## ☑️ 特性
31+
## :ballot_box_with_check: 特性
3332

3433
- 单文件运行,多平台兼容,无需安装任何依赖。Windows运行截图:
3534

cmd/kd.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ import (
2222
"go.uber.org/zap"
2323
)
2424

25-
var VERSION = "v0.0.4"
25+
var VERSION = "v0.0.5"
2626

2727
func showPrompt() {
2828
exename, err := pkg.GetExecutableBasename()
@@ -114,6 +114,7 @@ func flagUpdate(ctx *cli.Context, _ bool) (err error) {
114114

115115
if doUpdate {
116116
emoji.Println(":lightning: Let's update now")
117+
go daemon.KillDaemonIfRunning()
117118
err = update.UpdateBinary(VERSION)
118119
}
119120
return err
@@ -162,7 +163,7 @@ func flagEditConfig(*cli.Context, bool) error {
162163
}
163164

164165
func flagStatus(*cli.Context, bool) error {
165-
di := internal.GetDaemonInfo()
166+
di := daemon.GetDaemonInfo()
166167
d.EchoRun("运行和相关配置信息如下:")
167168
fmt.Printf(" Daemon端口:%s\n", di.Port)
168169
fmt.Printf(" Daemon PID:%d\n", di.PID)
@@ -254,7 +255,7 @@ func main() {
254255
}
255256
}
256257

257-
if cfg.FileExists && cfg.ModTime > internal.GetDaemonInfo().StartTime {
258+
if cfg.FileExists && cfg.ModTime > daemon.GetDaemonInfo().StartTime {
258259
d.EchoWarn("检测到配置文件发生修改,正在重启守护进程")
259260
flagStop(cCtx, true)
260261
flagDaemon(cCtx, true)

internal/client.go

Lines changed: 37 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ package internal
1010

1111
import (
1212
"fmt"
13+
"os"
1314
"regexp"
1415
"strings"
1516

@@ -18,20 +19,52 @@ import (
1819
"github.com/Karmenzind/kd/internal/daemon"
1920
"github.com/Karmenzind/kd/internal/model"
2021
q "github.com/Karmenzind/kd/internal/query"
22+
"github.com/Karmenzind/kd/pkg"
2123
d "github.com/Karmenzind/kd/pkg/decorate"
24+
"github.com/Karmenzind/kd/pkg/proc"
2225
"github.com/Karmenzind/kd/pkg/str"
2326
"go.uber.org/zap"
2427
)
2528

2629
func ensureDaemon(running chan bool) {
27-
if !daemon.ServerIsRunning() {
28-
err := daemon.StartDaemonProcess()
30+
p, _ := daemon.FindServerProcess()
31+
var err error
32+
if p == nil {
33+
d.EchoRun("未找到守护进程,正在启动...")
34+
err = daemon.StartDaemonProcess()
2935
if err != nil {
30-
d.EchoRun("未找到守护进程,正在启动...")
3136
d.EchoFatal(err.Error())
3237
}
33-
running <- true
38+
} else {
39+
exename, err := pkg.GetExecutablePath()
40+
if err == nil {
41+
runningExename, _ := p.Exe()
42+
// TODO (k): <2024-01-03> 增加检查版本
43+
if exename != runningExename {
44+
d.EchoWarn(fmt.Sprintf("正在运行的守护程序(%s)与当前程序(%s)文件信息或版本不一致,将尝试重新启动守护进程", runningExename, exename))
45+
err := proc.KillProcess(p)
46+
if err != nil {
47+
cmd := proc.GetKillCMD(p.Pid)
48+
d.EchoError(fmt.Sprintf("停止进程%v失败,请手动执行:", p.Pid))
49+
fmt.Println(cmd.String())
50+
os.Exit(1)
51+
}
52+
d.EchoRun("已终止,正在启动新的守护进程...")
53+
err = daemon.StartDaemonProcess()
54+
if err != nil {
55+
d.EchoFatal(err.Error())
56+
}
57+
}
58+
}
3459
}
60+
// if !daemon.ServerIsRunning() {
61+
// err := daemon.StartDaemonProcess()
62+
// if err != nil {
63+
// d.EchoRun("未找到守护进程,正在启动...")
64+
// d.EchoFatal(err.Error())
65+
// }
66+
// running <- true
67+
// }
3568
running <- true
3669
}
3770

internal/daemon/process.go

Lines changed: 53 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,51 @@ package daemon
22

33
import (
44
"fmt"
5+
"os"
56
"os/exec"
7+
"path/filepath"
68
"runtime"
7-
"strconv"
89
"strings"
9-
"syscall"
1010
"time"
1111

12+
"github.com/Karmenzind/kd/internal/cache"
1213
"github.com/Karmenzind/kd/pkg"
1314
d "github.com/Karmenzind/kd/pkg/decorate"
15+
"github.com/Karmenzind/kd/pkg/proc"
1416

1517
"github.com/shirou/gopsutil/v3/process"
1618
"go.uber.org/zap"
1719
)
1820

21+
type DaemonInfoType struct {
22+
StartTime int64
23+
Port string
24+
PID int
25+
}
26+
27+
var DaemonInfo = &DaemonInfoType{}
28+
29+
func RecordRunInfo(port string) {
30+
DaemonInfo.StartTime = time.Now().Unix()
31+
DaemonInfo.PID = os.Getpid()
32+
DaemonInfo.Port = port
33+
pkg.SaveJson(
34+
filepath.Join(cache.CACHE_RUN_PATH, "daemon.json"),
35+
DaemonInfo,
36+
)
37+
zap.S().Infof("Recorded running information of daemon %+v", DaemonInfo)
38+
}
39+
40+
func GetDaemonInfo() *DaemonInfoType {
41+
if *DaemonInfo == (DaemonInfoType{}) {
42+
err := pkg.LoadJson(filepath.Join(cache.CACHE_RUN_PATH, "daemon.json"), DaemonInfo)
43+
if err != nil {
44+
d.EchoFatal("获取守护进程信息失败,请执行`kd --stop && kd --daemon`")
45+
}
46+
}
47+
return DaemonInfo
48+
}
49+
1950
func getKdPIDs() {
2051
var cmd *exec.Cmd
2152

@@ -40,13 +71,28 @@ func FindServerProcess() (*process.Process, error) {
4071
if err != nil {
4172
return nil, err
4273
}
74+
di := GetDaemonInfo()
4375
for _, p := range processes {
4476
// XXX err
4577
n, _ := p.Name()
78+
if p.Pid == int32(di.PID) {
79+
zap.S().Debugf("Got daemon process %v via daemon info", di.PID)
80+
cmdslice, _ := p.CmdlineSlice()
81+
if len(cmdslice) > 1 && cmdslice[1] == "--server" {
82+
return p, nil
83+
}
84+
}
85+
4686
if n == "kd" || (runtime.GOOS == "windows" && n == "kd.exe") {
4787
cmd, _ := p.Cmdline()
88+
if p.Pid == 13328 {
89+
name, _ := p.Name()
90+
cmdslice, _ := p.CmdlineSlice()
91+
zap.S().Debugf("13328:Name: `%s` Cmd: `%s` cmdslice: `%+v`", name, cmd, cmdslice)
92+
}
93+
zap.S().Debugf("Found process kd.exe with CMD: %s", cmd)
4894
if strings.Contains(cmd, " --server") {
49-
zap.S().Debugf("Found process %+v Cmd: %s", p, cmd)
95+
zap.S().Debugf("Found process %+v Cmd: `%s`", p, cmd)
5096
return p, nil
5197
}
5298
}
@@ -91,43 +137,18 @@ func StartDaemonProcess() error {
91137

92138
func KillDaemonIfRunning() error {
93139
p, err := FindServerProcess()
94-
var trySysKill bool
95140
if err == nil {
96141
if p == nil {
97142
d.EchoOkay("未发现守护进程,无需停止")
98143
return nil
99-
} else if runtime.GOOS != "windows" {
100-
zap.S().Infof("Found running daemon PID: %d,", p.Pid)
101-
errSig := p.SendSignal(syscall.SIGINT)
102-
if errSig != nil {
103-
zap.S().Warnf("Failed to stop PID %d with syscall.SIGINT: %s", p.Pid, errSig)
104-
trySysKill = true
105-
}
106-
} else {
107-
trySysKill = true
108144
}
109145
} else {
110146
zap.S().Warnf("[process] Failed to find daemon: %s", err)
111-
trySysKill = true
112-
}
113-
pidStr := strconv.Itoa(int(p.Pid))
114-
115-
if trySysKill {
116-
var cmd *exec.Cmd
117-
switch runtime.GOOS {
118-
case "windows":
119-
cmd = exec.Command("taskkill", "/F", "/T", "/PID", pidStr)
120-
// cmd = exec.Command("taskkill", "/im", "kd", "/T", "/F")
121-
case "linux":
122-
cmd = exec.Command("kill", "-9", pidStr)
123-
// cmd = exec.Command("killall", "kd")
124-
}
125-
output, err := cmd.Output()
126-
zap.S().Infof("Executed '%s'. Output %s", cmd, output)
127-
if err != nil {
128-
zap.S().Warnf("Failed to kill daemon with system command. Error: %s", output, err)
129-
}
147+
return err
130148
}
149+
150+
err = proc.KillProcess(p)
151+
131152
if err == nil {
132153
zap.S().Info("Terminated daemon process.")
133154
d.EchoOkay("守护进程已经停止")

internal/server.go

Lines changed: 1 addition & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -6,52 +6,16 @@ import (
66
"fmt"
77
"io"
88
"net"
9-
"os"
10-
"path/filepath"
11-
"time"
129

13-
d "github.com/Karmenzind/kd/pkg/decorate"
14-
15-
"github.com/Karmenzind/kd/internal/cache"
1610
"github.com/Karmenzind/kd/internal/daemon"
1711
"github.com/Karmenzind/kd/internal/model"
1812
"github.com/Karmenzind/kd/internal/query"
19-
"github.com/Karmenzind/kd/pkg"
2013
"go.uber.org/zap"
2114
)
2215

2316
// TODO 支持自定义
2417
var SERVER_PORT = 19707
2518

26-
type DaemonInfoType struct {
27-
StartTime int64
28-
Port string
29-
PID int
30-
}
31-
32-
var DaemonInfo = &DaemonInfoType{}
33-
34-
func recordRunningInfo(port string) {
35-
DaemonInfo.StartTime = time.Now().Unix()
36-
DaemonInfo.PID = os.Getpid()
37-
DaemonInfo.Port = port
38-
pkg.SaveJson(
39-
filepath.Join(cache.CACHE_RUN_PATH, "daemon.json"),
40-
DaemonInfo,
41-
)
42-
zap.S().Infof("Recorded running information of daemon %+v", DaemonInfo)
43-
}
44-
45-
func GetDaemonInfo() *DaemonInfoType {
46-
if *DaemonInfo == (DaemonInfoType{}) {
47-
err := pkg.LoadJson(filepath.Join(cache.CACHE_RUN_PATH, "daemon.json"), DaemonInfo)
48-
if err != nil {
49-
d.EchoFatal("获取守护进程信息失败,请执行`kd --stop && kd --daemon`")
50-
}
51-
}
52-
return DaemonInfo
53-
}
54-
5519
func StartServer() (err error) {
5620
IS_SERVER = true
5721
addr := fmt.Sprintf("localhost:%d", SERVER_PORT)
@@ -67,7 +31,7 @@ func StartServer() (err error) {
6731
return err
6832
}
6933
daemon.InitCron()
70-
go recordRunningInfo(port)
34+
go daemon.RecordRunInfo(port)
7135

7236
fmt.Printf("Listening on host: %s, port: %s\n", host, port)
7337

pkg/proc/proc.go

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
package proc
2+
3+
import (
4+
"os/exec"
5+
"runtime"
6+
"strconv"
7+
"syscall"
8+
9+
"github.com/shirou/gopsutil/v3/process"
10+
"go.uber.org/zap"
11+
)
12+
13+
// not for Win
14+
func KillProcess(p *process.Process) (err error) {
15+
if runtime.GOOS != "windows" {
16+
errSig := p.SendSignal(syscall.SIGINT)
17+
if errSig == nil {
18+
if yes, errCheck := p.IsRunning(); errCheck == nil && !yes {
19+
zap.S().Infof("Stopped process %v with SIGINT.", p.Pid)
20+
return
21+
}
22+
} else {
23+
zap.S().Warnf("Failed to stop PID %v with syscall.SIGINT: %s", p.Pid, errSig)
24+
}
25+
}
26+
return SysKillPID(p.Pid)
27+
}
28+
29+
func GetKillCMD(pid int32) *exec.Cmd {
30+
pidStr := strconv.Itoa(int(pid))
31+
var cmd *exec.Cmd
32+
switch runtime.GOOS {
33+
case "windows":
34+
cmd = exec.Command("taskkill", "/F", "/T", "/PID", pidStr)
35+
// cmd = exec.Command("taskkill", "/im", "kd", "/T", "/F")
36+
case "linux":
37+
cmd = exec.Command("kill", "-9", pidStr)
38+
// cmd = exec.Command("killall", "kd")
39+
}
40+
return cmd
41+
}
42+
43+
func SysKillPID(pid int32) (err error) {
44+
cmd := GetKillCMD(pid)
45+
output, err := cmd.Output()
46+
zap.S().Infof("Executed '%s'. Output %s", cmd, output)
47+
if err != nil {
48+
zap.S().Warnf("Failed to kill %v with system command. Output: `%s` Error: `%s`", pid, output, err)
49+
}
50+
return
51+
}

plan.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@
4040
# BUG
4141

4242
## Risk
43-
- 实际文件名 不改的时候的process_name
43+
- 实际文件名 不改的时候的process_name,增加同时校验kd和当前文件名
4444

4545
## low priority
4646
- (action) linux 386

0 commit comments

Comments
 (0)