Files
go_process_manager/internal/app/logic/process_logic.go
2025-08-29 16:25:43 +08:00

246 lines
6.4 KiB
Go

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("进程类型错误")
}
if result.State.State != 1 {
return nil
}
result.State.manualStopFlag = true
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)
if process.State.State != 1 {
return true
}
wg.Add(1)
go func() {
defer wg.Done()
process.State.manualStopFlag = true
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
}