Browse Source

优化linux环境下进程管理

master
skyboy 10 months ago
parent
commit
c71961e078
  1. 28
      frontend/src/components/store/Store.vue
  2. 4
      godo/store/cmds.go
  3. 90
      godo/store/port.go
  4. 8
      godo/store/store.go

28
frontend/src/components/store/Store.vue

@ -28,7 +28,8 @@ async function install(item: any) {
}
const url = store.apiUrl + '/store/download'
const res = await download(item, url, postData)
console.log(res)
//console.log(res)
item.progress = 0
if(res.code < 0){
if(res.data && res.data.dependencies && res.data.dependencies.length > 0){
const names:any = []
@ -48,27 +49,6 @@ async function install(item: any) {
await store.checkProgress()
notifySuccess(t("store.installSuccess"))
}
// if (item.needInstall) {
// item.progress = 0
// const completion = await fetch(store.apiUrl + '/store/install?name=' + item.name)
// if (!completion.ok) {
// notifyError(t("store.installError"))
// return
// }
// const res = await completion.json()
// if (res.code && res.code < 0) {
// notifyError(res.message)
// return
// }
// if (res.data) {
// item.icon = res.data.icon
// }
// }
// await store.addDesktop(item);
// await store.checkProgress()
// notifySuccess(t("store.installSuccess"))
}
async function uninstall(item: any) {
@ -125,11 +105,11 @@ async function pauseApp(item: any) {
if (!res.ok) {
const msg = await res.text()
notifyError(msg)
return
//return
}
setTimeout(async () => {
await store.checkProgress()
}, 1000)
}, 3000)
}
async function restartApp(item: any) {

4
godo/store/cmds.go

@ -35,7 +35,7 @@ func runStart(storeInfo StoreInfo) error {
return fmt.Errorf("failed to get run cmd: %w", err)
}
if err := cmd.Start(); err != nil {
//log.Println("Error starting script:", err)
log.Printf("Error starting script: %v\nDetailed error: %v", err, cmd.Stderr)
return fmt.Errorf("error starting script: %v", err)
}
@ -61,6 +61,7 @@ func runStart(storeInfo StoreInfo) error {
}
func GetRunCmd(binPath string, cmds []string) (*exec.Cmd, error) {
var cmd *exec.Cmd
log.Printf("run script: %s", strings.Join(cmds, " "))
if binPath != "" {
if !libs.PathExists(binPath) {
return cmd, fmt.Errorf("script file %s does not exist", binPath)
@ -82,6 +83,7 @@ func GetRunCmd(binPath string, cmds []string) (*exec.Cmd, error) {
if len(cmds) == 0 {
return cmd, fmt.Errorf("no commands provided")
}
log.Printf("run script: %s", strings.Join(cmds, " "))
if len(cmds) > 1 {
cmd = exec.Command(cmds[0], cmds[1:]...)
} else {

90
godo/store/port.go

@ -9,7 +9,6 @@ import (
"net"
"net/http"
"os/exec"
"regexp"
"runtime"
"strconv"
"strings"
@ -26,7 +25,7 @@ type AllProcessesResponse struct {
Processes []ProcessSystemInfo `json:"processes"`
}
var processInfoRegex = regexp.MustCompile(`(\d+)\s+.*:\s*(\d+)\s+.*LISTEN\s+.*:(\d+)`)
//var processInfoRegex = regexp.MustCompile(`(\d+)\s+.*:\s*(\d+)\s+.*LISTEN\s+.*:(\d+)`)
func listAllProcesses() ([]ProcessSystemInfo, error) {
osType := runtime.GOOS
@ -37,7 +36,7 @@ func listAllProcesses() ([]ProcessSystemInfo, error) {
switch osType {
case "darwin", "linux":
cmd = exec.Command("lsof", "-i", "-n", "-P")
cmd = exec.Command("lsof", "-i")
case "windows":
cmd = exec.Command("netstat", "-ano")
default:
@ -48,31 +47,34 @@ func listAllProcesses() ([]ProcessSystemInfo, error) {
if err != nil {
return nil, fmt.Errorf("failed to list all processes: %v", err)
}
//lsofRegex := regexp.MustCompile(`(\d+)\s+(\S+\s+\S+)\s+(\d+)\s+(\w+)\s+IPv4\s+(\w+)\s+(\w+)\s+TCP\s+(\S+)\->\s+(\S+)\s+\((\w+)\)`)
processes := make([]ProcessSystemInfo, 0)
// 初始化映射用于去重
seenPIDs := make(map[int]bool)
// 解析输出
switch osType {
case "darwin", "linux":
scanner := bufio.NewScanner(bytes.NewBuffer(output)) // 使用bufio.Scanner
scanner := bufio.NewScanner(bytes.NewBuffer(output))
for scanner.Scan() {
line := scanner.Text()
matches := processInfoRegex.FindStringSubmatch(line)
if matches != nil {
pid, _ := strconv.Atoi(matches[1])
port, _ := strconv.Atoi(matches[3])
processName, err := getProcessName(osType, pid)
if err != nil {
log.Printf("Failed to get process name for PID %d: %v", pid, err)
continue
fields := strings.Fields(line)
if len(fields) >= 9 && fields[7] == "TCP" {
// 解析 PID 和其他字段
pid, _ := strconv.Atoi(fields[1])
name := fields[0]
// 解析本地端口
localPortStr := strings.Split(fields[8], ":")[1]
localPort, _ := strconv.Atoi(localPortStr)
if !seenPIDs[pid] {
seenPIDs[pid] = true
processes = append(processes, ProcessSystemInfo{
PID: pid,
Port: localPort,
Proto: "TCP",
Name: name,
})
}
processes = append(processes, ProcessSystemInfo{
PID: pid,
Port: port,
Proto: matches[2],
Name: processName,
})
}
}
case "windows":
@ -99,12 +101,15 @@ func listAllProcesses() ([]ProcessSystemInfo, error) {
log.Printf("Failed to convert port to integer: %v", err)
continue
}
processes = append(processes, ProcessSystemInfo{
PID: pid,
Port: portInt,
Proto: fields[0],
Name: processName,
})
if !seenPIDs[pid] {
seenPIDs[pid] = true
processes = append(processes, ProcessSystemInfo{
PID: pid,
Port: portInt,
Proto: fields[0],
Name: processName,
})
}
}
}
}
@ -153,18 +158,39 @@ func killProcessByName(name string) error {
switch osType {
case "darwin", "linux":
cmd = exec.Command("pkill", name)
// 使用 pgrep 查找进程 PID
pgrepCmd := exec.Command("pgrep", "-f", name)
pgrepOutput, err := pgrepCmd.CombinedOutput()
if err != nil {
return fmt.Errorf("failed to find process with name %s: %v", name, err)
}
// 将输出转换为字符串并按行分割
pids := strings.Split(strings.TrimSpace(string(pgrepOutput)), "\n")
// 对于每个找到的 PID,使用 kill 命令杀死进程
for _, pidStr := range pids {
pid, err := strconv.Atoi(pidStr)
if err != nil {
log.Printf("Failed to convert PID to integer: %v", err)
continue
}
// 每次循环使用新的 *exec.Cmd 实例
killCmd := exec.Command("kill", "-9", strconv.Itoa(pid))
if err := killCmd.Run(); err != nil {
log.Printf("Failed to kill process with PID %d: %v", pid, err)
}
}
case "windows":
cmd = exec.Command("taskkill", "/IM", name, "/F") // /F 表示强制结束
err = cmd.Run()
if err != nil {
log.Printf("Failed to kill process with name %s: %v", name, err)
}
default:
return fmt.Errorf("unsupported operating system")
}
err = cmd.Run()
if err != nil {
log.Printf("Failed to kill process with name %s: %v", name, err)
}
return err
}

8
godo/store/store.go

@ -150,10 +150,10 @@ func GetStoreInfoByPath(infoPath string) (StoreInfo, error) {
if err := json.Unmarshal(content, &storeInfo); err != nil {
return storeInfo, fmt.Errorf("failed to unmarshal info.json: %v", err)
}
scriptPath := storeInfo.Setting.BinPath
if !libs.PathExists(scriptPath) {
return storeInfo, fmt.Errorf("script file '%s' not found", scriptPath)
}
// scriptPath := storeInfo.Setting.BinPath
// if !libs.PathExists(scriptPath) {
// return storeInfo, fmt.Errorf("script file '%s' not found", scriptPath)
// }
return storeInfo, nil
}
func GetInstalled() []InstallInfo {

Loading…
Cancel
Save