fix:调试模式启动时,删除相关联端口的进程
This commit is contained in:
parent
b40fc75627
commit
eef39e0163
|
@ -16,7 +16,6 @@ import (
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
"strconv"
|
"strconv"
|
||||||
"syscall"
|
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -162,27 +161,34 @@ func (p *Proxy) restartBackend() error {
|
||||||
|
|
||||||
// 杀死之前的进程
|
// 杀死之前的进程
|
||||||
if p.backendPid != 0 {
|
if p.backendPid != 0 {
|
||||||
process, _ := os.FindProcess(p.backendPid)
|
err := util.KillProcess(p.backendPid)
|
||||||
if process != nil {
|
|
||||||
if runtime.GOOS == "windows" {
|
|
||||||
process.Kill()
|
|
||||||
} else {
|
|
||||||
err := process.Signal(syscall.SIGTERM)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
p.backendPid = 0
|
p.backendPid = 0
|
||||||
}
|
}
|
||||||
|
container := p.container
|
||||||
|
|
||||||
|
// 如果 发现之前有遗留并保存到本地的进程也要杀死
|
||||||
|
hadeApp := container.MustMake(contract.AppKey).(contract.App)
|
||||||
|
runtimeFolder := hadeApp.RuntimeFolder()
|
||||||
|
backendPidFile := filepath.Join(runtimeFolder, "backend.pid")
|
||||||
|
if util.Exists(backendPidFile) {
|
||||||
|
backendPid, _ := util.ReadFileToInt(backendPidFile)
|
||||||
|
if backendPid != p.backendPid {
|
||||||
|
util.KillProcess(p.backendPid)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 设置随机端口,真实后端的端口
|
// 设置随机端口,真实后端的端口
|
||||||
port := p.devConfig.Backend.Port
|
port := p.devConfig.Backend.Port
|
||||||
|
//尝试删除相关进程避免启动失败
|
||||||
|
util.FindProcessByPortAndKill(port)
|
||||||
hadeAddress := fmt.Sprintf(":" + port)
|
hadeAddress := fmt.Sprintf(":" + port)
|
||||||
// 使用命令行启动后端进程
|
// 使用命令行启动后端进程
|
||||||
|
|
||||||
// 根据系统设置输出文件名
|
// 根据系统设置输出文件名
|
||||||
config := p.container.MustMake(contract.ConfigKey).(contract.Config)
|
config := container.MustMake(contract.ConfigKey).(contract.Config)
|
||||||
execName := "./" + config.GetAppName()
|
execName := "./" + config.GetAppName()
|
||||||
if runtime.GOOS == "windows" {
|
if runtime.GOOS == "windows" {
|
||||||
execName += ".exe"
|
execName += ".exe"
|
||||||
|
@ -209,8 +215,21 @@ func (p *Proxy) restartFrontend() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
container := p.container
|
||||||
|
hadeApp := container.MustMake(contract.AppKey).(contract.App)
|
||||||
|
runtimeFolder := hadeApp.RuntimeFolder()
|
||||||
|
frontendPidFile := filepath.Join(runtimeFolder, "frontend.pid")
|
||||||
|
if util.Exists(frontendPidFile) {
|
||||||
|
frontendPid, _ := util.ReadFileToInt(frontendPidFile)
|
||||||
|
if frontendPid != p.frontendPid {
|
||||||
|
util.KillProcess(frontendPid)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 否则开启npm run serve
|
// 否则开启npm run serve
|
||||||
port := p.devConfig.Frontend.Port
|
port := p.devConfig.Frontend.Port
|
||||||
|
//尝试删除相关进程避免启动失败
|
||||||
|
util.FindProcessByPortAndKill(port)
|
||||||
path, err := exec.LookPath("npm")
|
path, err := exec.LookPath("npm")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -266,12 +285,17 @@ func (p *Proxy) startProxy(startFrontend, startBackend bool) error {
|
||||||
|
|
||||||
// 设置反向代理
|
// 设置反向代理
|
||||||
proxyReverse := p.newProxyReverseProxy(frontendURL, backendURL)
|
proxyReverse := p.newProxyReverseProxy(frontendURL, backendURL)
|
||||||
|
//尝试删除相关进程避免启动失败
|
||||||
|
util.FindProcessByPortAndKill(p.devConfig.Port)
|
||||||
p.proxyServer = &http.Server{
|
p.proxyServer = &http.Server{
|
||||||
Addr: "127.0.0.1:" + p.devConfig.Port,
|
Addr: "127.0.0.1:" + p.devConfig.Port,
|
||||||
Handler: proxyReverse,
|
Handler: proxyReverse,
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Println("代理服务启动:", "http://"+p.proxyServer.Addr)
|
fmt.Println("代理服务启动:", "http://"+p.proxyServer.Addr)
|
||||||
|
//记录pid信息到文件当中
|
||||||
|
recordPidToFile(p)
|
||||||
|
|
||||||
// 启动proxy服务
|
// 启动proxy服务
|
||||||
err = p.proxyServer.ListenAndServe()
|
err = p.proxyServer.ListenAndServe()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -387,18 +411,25 @@ var devAllCommand = &cobra.Command{
|
||||||
if err := proxy.startProxy(true, true); err != nil {
|
if err := proxy.startProxy(true, true); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
//记录后端的pid到本地文件
|
|
||||||
container := c.GetContainer()
|
|
||||||
app := container.MustMake(contract.AppKey).(contract.App)
|
|
||||||
storageFolder := app.StorageFolder()
|
|
||||||
pidFile := filepath.Join(storageFolder, "backend.pid")
|
|
||||||
// 将 backendPid 写入文件
|
|
||||||
pid := strconv.Itoa(proxy.backendPid) // 将 pid 转为字符串
|
|
||||||
if err := os.WriteFile(pidFile, []byte(pid), 0666); err != nil {
|
|
||||||
return fmt.Errorf("无法写入 PID 文件: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func recordPidToFile(proxy *Proxy) {
|
||||||
|
container := proxy.container
|
||||||
|
//记录后端的pid到本地文件
|
||||||
|
app := container.MustMake(contract.AppKey).(contract.App)
|
||||||
|
storageFolder := app.RuntimeFolder()
|
||||||
|
backendPidFile := filepath.Join(storageFolder, "backend.pid")
|
||||||
|
frontendPidFile := filepath.Join(storageFolder, "frontend.pid")
|
||||||
|
// 将 backendPid 写入文件
|
||||||
|
backendPid := strconv.Itoa(proxy.backendPid) // 将 pid 转为字符串
|
||||||
|
if err := os.WriteFile(backendPidFile, []byte(backendPid), 0666); err != nil {
|
||||||
|
fmt.Println("无法写入 PID 文件: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
frontendPid := strconv.Itoa(proxy.frontendPid) // 将 pid 转为字符串
|
||||||
|
if err := os.WriteFile(frontendPidFile, []byte(frontendPid), 0666); err != nil {
|
||||||
|
fmt.Println("无法写入 PID 文件: %w", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,7 +1,13 @@
|
||||||
package util
|
package util
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
"runtime"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
"syscall"
|
"syscall"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -27,3 +33,81 @@ func CheckProcessExist(pid int) bool {
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func KillProcess(pid int) error {
|
||||||
|
process, _ := os.FindProcess(pid)
|
||||||
|
if process != nil {
|
||||||
|
if runtime.GOOS == "windows" {
|
||||||
|
err := process.Kill()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
fmt.Println("成功杀死进程,PID:" + strconv.Itoa(pid))
|
||||||
|
} else {
|
||||||
|
err := process.Signal(syscall.SIGTERM)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func FindProcessByPortAndKill(port string) {
|
||||||
|
byPort, err := findProcessByPort(port)
|
||||||
|
if err == nil {
|
||||||
|
killProcess(byPort)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查找占用指定端口的进程ID
|
||||||
|
func findProcessByPort(port string) (string, error) {
|
||||||
|
var cmd *exec.Cmd
|
||||||
|
|
||||||
|
// 根据操作系统选择命令
|
||||||
|
if runtime.GOOS == "windows" {
|
||||||
|
cmd = exec.Command("cmd", "/C", fmt.Sprintf("netstat -ano | findstr :%s", port))
|
||||||
|
} else {
|
||||||
|
cmd = exec.Command("sh", "-c", fmt.Sprintf("lsof -i :%s -t", port))
|
||||||
|
}
|
||||||
|
|
||||||
|
var out bytes.Buffer
|
||||||
|
cmd.Stdout = &out
|
||||||
|
err := cmd.Run()
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("failed to execute command: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取 PID 并进行处理
|
||||||
|
pid := strings.TrimSpace(out.String())
|
||||||
|
if pid == "" {
|
||||||
|
return "", fmt.Errorf("no process found on port %s", port)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 对于 Windows,netstat 输出可能有多行,取第一行的 PID
|
||||||
|
if runtime.GOOS == "windows" {
|
||||||
|
lines := strings.Split(pid, "\n")
|
||||||
|
fields := strings.Fields(lines[0])
|
||||||
|
if len(fields) >= 5 {
|
||||||
|
pid = fields[4]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return pid, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// 杀死指定 PID 的进程
|
||||||
|
func killProcess(pid string) error {
|
||||||
|
var cmd *exec.Cmd
|
||||||
|
// 根据操作系统选择命令
|
||||||
|
if runtime.GOOS == "windows" {
|
||||||
|
cmd = exec.Command("taskkill", "/PID", pid, "/F")
|
||||||
|
} else {
|
||||||
|
cmd = exec.Command("kill", "-9", pid)
|
||||||
|
}
|
||||||
|
err := cmd.Run()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to kill process %s: %v", pid, err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
|
@ -2,11 +2,13 @@ package util
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"github.com/pkg/errors"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -125,3 +127,17 @@ func CopyDir(srcDir, dstDir string) error {
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ReadFileToString(file string) (string, error) {
|
||||||
|
// 读取 pid 文件内容
|
||||||
|
data, err := os.ReadFile(file)
|
||||||
|
if err != nil {
|
||||||
|
return "", errors.Wrap(err, "读取文件失败: "+file)
|
||||||
|
}
|
||||||
|
return string(data), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func ReadFileToInt(file string) (int, error) {
|
||||||
|
toString, _ := ReadFileToString(file)
|
||||||
|
return strconv.Atoi(toString)
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue