package logic import ( "errors" "runtime" "slices" "strings" "sync" "github.com/lzh-1625/go_process_manager/config" "github.com/lzh-1625/go_process_manager/internal/app/eum" "github.com/lzh-1625/go_process_manager/internal/app/model" "github.com/lzh-1625/go_process_manager/internal/app/repository" "github.com/lzh-1625/go_process_manager/log" "github.com/lzh-1625/go_process_manager/utils" "github.com/shirou/gopsutil/mem" ) type processCtlLogic struct { processMap sync.Map } var ( ProcessCtlLogic = new(processCtlLogic) ) func (p *processCtlLogic) AddProcess(uuid int, process *ProcessBase) { p.processMap.Store(uuid, process) } func (p *processCtlLogic) KillProcess(uuid int) error { value, ok := p.processMap.Load(uuid) if !ok { return errors.New("进程不存在") } result, ok := value.(*ProcessBase) if !ok { return errors.New("进程类型错误") } return result.Kill() } func (p *processCtlLogic) GetProcess(uuid int) (*ProcessBase, error) { process, ok := p.processMap.Load(uuid) if !ok { return nil, errors.New("process not exist") } result, ok := process.(*ProcessBase) if !ok { return nil, errors.New("process type error") } return result, nil } func (p *processCtlLogic) KillAllProcess() { wg := sync.WaitGroup{} p.processMap.Range(func(key, value any) bool { process := value.(*ProcessBase) wg.Add(1) go func() { defer wg.Done() process.Kill() }() return true }) wg.Wait() } func (p *processCtlLogic) KillAllProcessByUserName(userName string) { stopPermissionProcess := repository.PermissionRepository.GetProcessNameByPermission(userName, eum.OperationStop) wg := sync.WaitGroup{} p.processMap.Range(func(key, value any) bool { process := value.(*ProcessBase) if !slices.Contains(stopPermissionProcess, process.Name) { return true } wg.Add(1) go func() { defer wg.Done() process.Kill() }() return true }) wg.Wait() } func (p *processCtlLogic) DeleteProcess(uuid int) { p.processMap.Delete(uuid) } func (p *processCtlLogic) GetProcessList() []model.ProcessInfo { processConfiglist := repository.ProcessRepository.GetAllProcessConfig() return p.getProcessInfoList(processConfiglist) } func (p *processCtlLogic) GetProcessListByUser(username string) []model.ProcessInfo { processConfiglist := repository.ProcessRepository.GetProcessConfigByUser(username) return p.getProcessInfoList(processConfiglist) } func (p *processCtlLogic) getProcessInfoList(processConfiglist []model.Process) []model.ProcessInfo { processInfoList := []model.ProcessInfo{} for _, v := range processConfiglist { pi := model.ProcessInfo{ Name: v.Name, Uuid: v.Uuid, } process, err := p.GetProcess(v.Uuid) if err != nil { continue } pi.State.Info = process.State.Info pi.State.State = process.State.State pi.StartTime = process.GetStartTimeFormat() pi.User = process.GetUserString() pi.Usage.Cpu = process.performanceStatus.cpu pi.Usage.Mem = process.performanceStatus.mem if config.CF.PerformanceCapacityDisplay { pi.Usage.CpuCapacity = float64(runtime.NumCPU()) * 100.0 pi.Usage.MemCapacity = float64(utils.UnwarpIgnore(mem.VirtualMemory()).Total >> 10) } pi.Usage.Time = process.performanceStatus.time pi.TermType = process.Type() pi.CgroupEnable = process.Config.cgroupEnable pi.CpuLimit = process.Config.cpuLimit pi.MemoryLimit = process.Config.memoryLimit processInfoList = append(processInfoList, pi) } return processInfoList } func (p *processCtlLogic) ProcessStartAll() { p.processMap.Range(func(key, value any) bool { process := value.(*ProcessBase) err := process.Start() if err != nil { log.Logger.Errorw("进程启动失败", "name", process.Name) } return true }) } func (p *processCtlLogic) RunPrcessById(id int) (*ProcessBase, error) { config, err := repository.ProcessRepository.GetProcessConfigById(id) if err != nil { return nil, err } proc, err := p.RunNewProcess(config) if err != nil { log.Logger.Warnw("初始化启动进程失败", config.Name, "name", "err", err) return nil, err } p.AddProcess(id, proc) return proc, nil } func (p *processCtlLogic) ProcessInit() { config := repository.ProcessRepository.GetAllProcessConfig() for _, v := range config { proc, err := p.NewProcess(v) if err != nil { log.Logger.Warnw("初始化启动进程失败", v.Name, "name", "err", err) continue } if v.AutoRestart { err := proc.Start() if err != nil { log.Logger.Warnw("初始化启动进程失败", v.Name, "name", "err", err) continue } } p.AddProcess(v.Uuid, proc) } } func (p *processCtlLogic) ProcesStartAllByUsername(userName string) { startPermissionProcess := repository.PermissionRepository.GetProcessNameByPermission(userName, eum.OperationStart) p.processMap.Range(func(key, value any) bool { process := value.(*ProcessBase) if !slices.Contains(startPermissionProcess, process.Name) { return true } err := process.Start() if err != nil { log.Logger.Errorw("进程启动失败", "name", process.Name) } return true }) } func (p *processCtlLogic) UpdateProcessConfig(config model.Process) error { process, ok := p.processMap.Load(config.Uuid) if !ok { return errors.New("进程获取失败") } result, ok := process.(*ProcessBase) if !ok { return errors.New("进程类型错误") } if !result.Lock.TryLock() { return errors.New("进程当前正在被使用") } defer result.Lock.Unlock() result.Config.logReport = config.LogReport result.Config.PushIds = utils.JsonStrToStruct[[]int64](config.PushIds) result.Config.cgroupEnable = config.CgroupEnable result.Config.memoryLimit = config.MemoryLimit result.Config.cpuLimit = config.CpuLimit result.Config.AutoRestart = config.AutoRestart result.Config.compulsoryRestart = config.CompulsoryRestart result.StartCommand = strings.Fields(config.Cmd) result.WorkDir = config.Cwd result.Name = config.Name return nil } func (p *processCtlLogic) NewProcess(config model.Process) (proc *ProcessBase, err error) { switch config.TermType { case eum.TerminalStd: proc = NewProcessStd(config) case eum.TerminalPty: proc = NewProcessPty(config) default: err = errors.New("终端类型错误") } return } func (p *processCtlLogic) RunNewProcess(config model.Process) (proc *ProcessBase, err error) { proc, err = p.NewProcess(config) if err != nil { return } err = proc.Start() return }