Skip to content

Commit eb0389b

Browse files
Copilotnomeguy
andcommitted
feat: implement StopOldInstance() to kill old process on startup
Co-authored-by: nomeguy <85475922+nomeguy@users.noreply.github.com>
1 parent 72eaaa6 commit eb0389b

File tree

3 files changed

+151
-1
lines changed

3 files changed

+151
-1
lines changed

main.go

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
package main
1616

1717
import (
18+
"fmt"
19+
1820
"github.com/beego/beego"
1921
"github.com/beego/beego/plugins/cors"
2022
_ "github.com/beego/beego/session/redis"
@@ -25,6 +27,7 @@ import (
2527
"github.com/casbin/caswaf/routers"
2628
"github.com/casbin/caswaf/run"
2729
"github.com/casbin/caswaf/service"
30+
"github.com/casbin/caswaf/util"
2831
)
2932

3033
func main() {
@@ -67,5 +70,12 @@ func main() {
6770

6871
service.Start()
6972

70-
beego.Run()
73+
port := beego.AppConfig.DefaultInt("httpport", 17000)
74+
75+
err := util.StopOldInstance(port)
76+
if err != nil {
77+
panic(err)
78+
}
79+
80+
beego.Run(fmt.Sprintf(":%v", port))
7181
}

util/process.go

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
// Copyright 2023 The casbin Authors. All Rights Reserved.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package util
16+
17+
import (
18+
"fmt"
19+
"os"
20+
"os/exec"
21+
"runtime"
22+
"strconv"
23+
"strings"
24+
)
25+
26+
func getPidByPort(port int) (int, error) {
27+
var cmd *exec.Cmd
28+
switch runtime.GOOS {
29+
case "windows":
30+
cmd = exec.Command("cmd", "/c", "netstat -ano | findstr :"+strconv.Itoa(port))
31+
case "darwin", "linux":
32+
cmd = exec.Command("lsof", "-t", "-i", ":"+strconv.Itoa(port))
33+
default:
34+
return 0, fmt.Errorf("unsupported OS: %s", runtime.GOOS)
35+
}
36+
37+
output, err := cmd.Output()
38+
if err != nil {
39+
if exitErr, ok := err.(*exec.ExitError); ok {
40+
if exitErr.ExitCode() == 1 {
41+
return 0, nil
42+
}
43+
} else {
44+
return 0, err
45+
}
46+
}
47+
48+
lines := strings.Split(string(output), "\n")
49+
for _, line := range lines {
50+
fields := strings.Fields(line)
51+
if len(fields) > 0 {
52+
if runtime.GOOS == "windows" {
53+
if fields[1] == "0.0.0.0:"+strconv.Itoa(port) {
54+
pid, err := strconv.Atoi(fields[len(fields)-1])
55+
if err != nil {
56+
return 0, err
57+
}
58+
59+
return pid, nil
60+
}
61+
} else {
62+
pid, err := strconv.Atoi(fields[0])
63+
if err != nil {
64+
return 0, err
65+
}
66+
67+
return pid, nil
68+
}
69+
}
70+
}
71+
72+
return 0, nil
73+
}
74+
75+
func StopOldInstance(port int) error {
76+
pid, err := getPidByPort(port)
77+
if err != nil {
78+
return err
79+
}
80+
if pid == 0 {
81+
return nil
82+
}
83+
84+
process, err := os.FindProcess(pid)
85+
if err != nil {
86+
return err
87+
}
88+
89+
err = process.Kill()
90+
if err != nil {
91+
return err
92+
} else {
93+
fmt.Printf("The old instance with pid: %d has been stopped\n", pid)
94+
}
95+
96+
return nil
97+
}

util/process_test.go

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
// Copyright 2023 The casbin Authors. All Rights Reserved.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
//go:build !skipCi
16+
// +build !skipCi
17+
18+
package util
19+
20+
import (
21+
"testing"
22+
)
23+
24+
func TestStopOldInstance(t *testing.T) {
25+
// Test with a port that's not in use
26+
// This should succeed without error
27+
err := StopOldInstance(54321)
28+
if err != nil {
29+
t.Errorf("StopOldInstance failed for unused port: %v", err)
30+
}
31+
}
32+
33+
func TestGetPidByPort(t *testing.T) {
34+
// Test with a port that's not in use
35+
// Should return 0 and no error
36+
pid, err := getPidByPort(54321)
37+
if err != nil {
38+
t.Errorf("getPidByPort failed: %v", err)
39+
}
40+
if pid != 0 {
41+
t.Errorf("Expected pid to be 0 for unused port, got %d", pid)
42+
}
43+
}

0 commit comments

Comments
 (0)