mirror of
https://github.com/lzh-1625/go_process_manager.git
synced 2025-09-27 12:22:13 +08:00
246 lines
6.4 KiB
Go
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
|
|
}
|