优化linux环境下进程管理
This commit is contained in:
parent
884f390c05
commit
c71961e078
4 changed files with 69 additions and 61 deletions
|
|
@ -28,7 +28,8 @@ async function install(item: any) {
|
||||||
}
|
}
|
||||||
const url = store.apiUrl + '/store/download'
|
const url = store.apiUrl + '/store/download'
|
||||||
const res = await download(item, url, postData)
|
const res = await download(item, url, postData)
|
||||||
console.log(res)
|
//console.log(res)
|
||||||
|
item.progress = 0
|
||||||
if(res.code < 0){
|
if(res.code < 0){
|
||||||
if(res.data && res.data.dependencies && res.data.dependencies.length > 0){
|
if(res.data && res.data.dependencies && res.data.dependencies.length > 0){
|
||||||
const names:any = []
|
const names:any = []
|
||||||
|
|
@ -48,27 +49,6 @@ async function install(item: any) {
|
||||||
await store.checkProgress()
|
await store.checkProgress()
|
||||||
notifySuccess(t("store.installSuccess"))
|
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) {
|
async function uninstall(item: any) {
|
||||||
|
|
@ -125,11 +105,11 @@ async function pauseApp(item: any) {
|
||||||
if (!res.ok) {
|
if (!res.ok) {
|
||||||
const msg = await res.text()
|
const msg = await res.text()
|
||||||
notifyError(msg)
|
notifyError(msg)
|
||||||
return
|
//return
|
||||||
}
|
}
|
||||||
setTimeout(async () => {
|
setTimeout(async () => {
|
||||||
await store.checkProgress()
|
await store.checkProgress()
|
||||||
}, 1000)
|
}, 3000)
|
||||||
|
|
||||||
}
|
}
|
||||||
async function restartApp(item: any) {
|
async function restartApp(item: any) {
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,7 @@ func runStart(storeInfo StoreInfo) error {
|
||||||
return fmt.Errorf("failed to get run cmd: %w", err)
|
return fmt.Errorf("failed to get run cmd: %w", err)
|
||||||
}
|
}
|
||||||
if err := cmd.Start(); err != nil {
|
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)
|
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) {
|
func GetRunCmd(binPath string, cmds []string) (*exec.Cmd, error) {
|
||||||
var cmd *exec.Cmd
|
var cmd *exec.Cmd
|
||||||
|
log.Printf("run script: %s", strings.Join(cmds, " "))
|
||||||
if binPath != "" {
|
if binPath != "" {
|
||||||
if !libs.PathExists(binPath) {
|
if !libs.PathExists(binPath) {
|
||||||
return cmd, fmt.Errorf("script file %s does not exist", 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 {
|
if len(cmds) == 0 {
|
||||||
return cmd, fmt.Errorf("no commands provided")
|
return cmd, fmt.Errorf("no commands provided")
|
||||||
}
|
}
|
||||||
|
log.Printf("run script: %s", strings.Join(cmds, " "))
|
||||||
if len(cmds) > 1 {
|
if len(cmds) > 1 {
|
||||||
cmd = exec.Command(cmds[0], cmds[1:]...)
|
cmd = exec.Command(cmds[0], cmds[1:]...)
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,6 @@ import (
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"regexp"
|
|
||||||
"runtime"
|
"runtime"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
@ -26,7 +25,7 @@ type AllProcessesResponse struct {
|
||||||
Processes []ProcessSystemInfo `json:"processes"`
|
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) {
|
func listAllProcesses() ([]ProcessSystemInfo, error) {
|
||||||
osType := runtime.GOOS
|
osType := runtime.GOOS
|
||||||
|
|
@ -37,7 +36,7 @@ func listAllProcesses() ([]ProcessSystemInfo, error) {
|
||||||
|
|
||||||
switch osType {
|
switch osType {
|
||||||
case "darwin", "linux":
|
case "darwin", "linux":
|
||||||
cmd = exec.Command("lsof", "-i", "-n", "-P")
|
cmd = exec.Command("lsof", "-i")
|
||||||
case "windows":
|
case "windows":
|
||||||
cmd = exec.Command("netstat", "-ano")
|
cmd = exec.Command("netstat", "-ano")
|
||||||
default:
|
default:
|
||||||
|
|
@ -48,31 +47,34 @@ func listAllProcesses() ([]ProcessSystemInfo, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to list all processes: %v", err)
|
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)
|
processes := make([]ProcessSystemInfo, 0)
|
||||||
|
// 初始化映射用于去重
|
||||||
|
seenPIDs := make(map[int]bool)
|
||||||
// 解析输出
|
// 解析输出
|
||||||
switch osType {
|
switch osType {
|
||||||
case "darwin", "linux":
|
case "darwin", "linux":
|
||||||
scanner := bufio.NewScanner(bytes.NewBuffer(output)) // 使用bufio.Scanner
|
scanner := bufio.NewScanner(bytes.NewBuffer(output))
|
||||||
|
|
||||||
for scanner.Scan() {
|
for scanner.Scan() {
|
||||||
line := scanner.Text()
|
line := scanner.Text()
|
||||||
matches := processInfoRegex.FindStringSubmatch(line)
|
fields := strings.Fields(line)
|
||||||
if matches != nil {
|
if len(fields) >= 9 && fields[7] == "TCP" {
|
||||||
pid, _ := strconv.Atoi(matches[1])
|
// 解析 PID 和其他字段
|
||||||
port, _ := strconv.Atoi(matches[3])
|
pid, _ := strconv.Atoi(fields[1])
|
||||||
processName, err := getProcessName(osType, pid)
|
name := fields[0]
|
||||||
if err != nil {
|
// 解析本地端口
|
||||||
log.Printf("Failed to get process name for PID %d: %v", pid, err)
|
localPortStr := strings.Split(fields[8], ":")[1]
|
||||||
continue
|
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":
|
case "windows":
|
||||||
|
|
@ -99,12 +101,15 @@ func listAllProcesses() ([]ProcessSystemInfo, error) {
|
||||||
log.Printf("Failed to convert port to integer: %v", err)
|
log.Printf("Failed to convert port to integer: %v", err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
processes = append(processes, ProcessSystemInfo{
|
if !seenPIDs[pid] {
|
||||||
PID: pid,
|
seenPIDs[pid] = true
|
||||||
Port: portInt,
|
processes = append(processes, ProcessSystemInfo{
|
||||||
Proto: fields[0],
|
PID: pid,
|
||||||
Name: processName,
|
Port: portInt,
|
||||||
})
|
Proto: fields[0],
|
||||||
|
Name: processName,
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -153,18 +158,39 @@ func killProcessByName(name string) error {
|
||||||
|
|
||||||
switch osType {
|
switch osType {
|
||||||
case "darwin", "linux":
|
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":
|
case "windows":
|
||||||
cmd = exec.Command("taskkill", "/IM", name, "/F") // /F 表示强制结束
|
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:
|
default:
|
||||||
return fmt.Errorf("unsupported operating system")
|
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
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -150,10 +150,10 @@ func GetStoreInfoByPath(infoPath string) (StoreInfo, error) {
|
||||||
if err := json.Unmarshal(content, &storeInfo); err != nil {
|
if err := json.Unmarshal(content, &storeInfo); err != nil {
|
||||||
return storeInfo, fmt.Errorf("failed to unmarshal info.json: %v", err)
|
return storeInfo, fmt.Errorf("failed to unmarshal info.json: %v", err)
|
||||||
}
|
}
|
||||||
scriptPath := storeInfo.Setting.BinPath
|
// scriptPath := storeInfo.Setting.BinPath
|
||||||
if !libs.PathExists(scriptPath) {
|
// if !libs.PathExists(scriptPath) {
|
||||||
return storeInfo, fmt.Errorf("script file '%s' not found", scriptPath)
|
// return storeInfo, fmt.Errorf("script file '%s' not found", scriptPath)
|
||||||
}
|
// }
|
||||||
return storeInfo, nil
|
return storeInfo, nil
|
||||||
}
|
}
|
||||||
func GetInstalled() []InstallInfo {
|
func GetInstalled() []InstallInfo {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue