mirror of
https://github.com/lzh-1625/go_process_manager.git
synced 2025-10-21 15:09:23 +08:00
cross platform pty support
This commit is contained in:
4
go.mod
4
go.mod
@@ -9,12 +9,14 @@ require (
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/aymanbagabas/go-pty v0.2.2 // indirect
|
||||
github.com/cilium/ebpf v0.16.0 // indirect
|
||||
github.com/containerd/log v0.1.0 // indirect
|
||||
github.com/coreos/go-systemd/v22 v22.5.0 // indirect
|
||||
github.com/docker/go-units v0.5.0 // indirect
|
||||
github.com/go-ole/go-ole v1.2.6 // indirect
|
||||
github.com/godbus/dbus/v5 v5.1.0 // indirect
|
||||
github.com/iamacarpet/go-winpty v1.0.2 // indirect
|
||||
github.com/josharian/intern v1.0.0 // indirect
|
||||
github.com/mailru/easyjson v0.7.7 // indirect
|
||||
github.com/moby/sys/userns v0.1.0 // indirect
|
||||
@@ -22,6 +24,7 @@ require (
|
||||
github.com/sirupsen/logrus v1.9.3 // indirect
|
||||
github.com/tklauser/go-sysconf v0.3.13 // indirect
|
||||
github.com/tklauser/numcpus v0.7.0 // indirect
|
||||
github.com/u-root/u-root v0.11.0 // indirect
|
||||
github.com/yusufpapurcu/wmi v1.2.4 // indirect
|
||||
golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f // indirect
|
||||
golang.org/x/sync v0.9.0 // indirect
|
||||
@@ -93,6 +96,7 @@ require (
|
||||
github.com/olivere/elastic/v7 v7.0.32
|
||||
github.com/panjf2000/ants/v2 v2.10.0
|
||||
github.com/robfig/cron/v3 v3.0.1
|
||||
github.com/runletapp/go-console v0.0.0-20211204140000-27323a28410a
|
||||
github.com/shirou/gopsutil v3.21.11+incompatible
|
||||
github.com/timandy/routine v1.1.4
|
||||
go.uber.org/zap v1.26.0
|
||||
|
9
go.sum
9
go.sum
@@ -1,3 +1,5 @@
|
||||
github.com/aymanbagabas/go-pty v0.2.2 h1:YZREB4eSj+1xdbbItIokX0ekjjeifgJOA+ZvxU4/WM8=
|
||||
github.com/aymanbagabas/go-pty v0.2.2/go.mod h1:gfvlwH+0U66BCwxJREjJaAOEs9H1OFf3YFjI9WSiZ04=
|
||||
github.com/bytedance/sonic v1.11.6 h1:oUp34TzMlL+OY1OUWxHqsdkgC/Zfc85zGqw9siXjrc0=
|
||||
github.com/bytedance/sonic v1.11.6/go.mod h1:LysEHSvpvDySVdC2f87zGWf6CIKJcAvqab1ZaiQtds4=
|
||||
github.com/bytedance/sonic/loader v0.1.1 h1:c+e5Pt1k/cy5wMveRDyk2X4B9hF4g7an8N3zCYjJFNM=
|
||||
@@ -14,6 +16,7 @@ github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I=
|
||||
github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo=
|
||||
github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs=
|
||||
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
|
||||
github.com/creack/pty v1.1.17/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4=
|
||||
github.com/creack/pty v1.1.21 h1:1/QdRyBaHHJP61QkWMXlOIBfsgdDeeKfK8SYVUWJKf0=
|
||||
github.com/creack/pty v1.1.21/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
@@ -73,6 +76,8 @@ github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
|
||||
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY=
|
||||
github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY=
|
||||
github.com/iamacarpet/go-winpty v1.0.2 h1:jwPVTYrjAHZx6Mcm6K5i9G4opMp5TblEHH5EQCl/Gzw=
|
||||
github.com/iamacarpet/go-winpty v1.0.2/go.mod h1:/GHKJicG/EVRQIK1IQikMYBakBkhj/3hTjLgdzYsmpI=
|
||||
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
|
||||
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
|
||||
github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
|
||||
@@ -141,6 +146,8 @@ github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs=
|
||||
github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro=
|
||||
github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M=
|
||||
github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA=
|
||||
github.com/runletapp/go-console v0.0.0-20211204140000-27323a28410a h1:1hh8CSomjZSJPk7AgHV8o33Su13bZby81PrC6pIvJqQ=
|
||||
github.com/runletapp/go-console v0.0.0-20211204140000-27323a28410a/go.mod h1:9Y3jw1valnPKqsYSsBWxQNAuxqNSBuwd2ZEeElxgNUI=
|
||||
github.com/shirou/gopsutil v3.21.11+incompatible h1:+1+c1VGhc88SSonWP6foOcLhvnKlUeu/erjjvaPEYiI=
|
||||
github.com/shirou/gopsutil v3.21.11+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
|
||||
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
|
||||
@@ -166,6 +173,8 @@ github.com/tklauser/numcpus v0.7.0 h1:yjuerZP127QG9m5Zh/mSO4wqurYil27tHrqwRoRjpr
|
||||
github.com/tklauser/numcpus v0.7.0/go.mod h1:bb6dMVcj8A42tSE7i32fsIUCbQNllK5iDguyOZRUzAY=
|
||||
github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
|
||||
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
|
||||
github.com/u-root/u-root v0.11.0 h1:6gCZLOeRyevw7gbTwMj3fKxnr9+yHFlgF3N7udUVNO8=
|
||||
github.com/u-root/u-root v0.11.0/go.mod h1:DBkDtiZyONk9hzVEdB/PWI9B4TxDkElWlVTHseglrZY=
|
||||
github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE=
|
||||
github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
|
||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
|
@@ -2,7 +2,7 @@ package service
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os/exec"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
@@ -15,10 +15,6 @@ import (
|
||||
"github.com/lzh-1625/go_process_manager/internal/app/model"
|
||||
"github.com/lzh-1625/go_process_manager/log"
|
||||
|
||||
"github.com/containerd/cgroups/v3"
|
||||
"github.com/containerd/cgroups/v3/cgroup1"
|
||||
"github.com/containerd/cgroups/v3/cgroup2"
|
||||
"github.com/opencontainers/runtime-spec/specs-go"
|
||||
pu "github.com/shirou/gopsutil/process"
|
||||
)
|
||||
|
||||
@@ -30,16 +26,18 @@ type Process interface {
|
||||
readInit()
|
||||
doOnInit()
|
||||
doOnKilled()
|
||||
initCgroup()
|
||||
Start() error
|
||||
Type() constants.TerminalType
|
||||
Wait() (*os.ProcessState, error)
|
||||
SetTerminalSize(int, int)
|
||||
}
|
||||
|
||||
type ProcessBase struct {
|
||||
Process
|
||||
p *os.Process
|
||||
Name string
|
||||
Pid int
|
||||
cmd *exec.Cmd
|
||||
StartCommand []string
|
||||
WorkDir string
|
||||
Lock sync.Mutex
|
||||
@@ -89,7 +87,7 @@ type ConnectInstance interface {
|
||||
}
|
||||
|
||||
func (p *ProcessBase) watchDog() {
|
||||
state, _ := p.cmd.Process.Wait()
|
||||
state, _ := p.p.Wait()
|
||||
if p.cgroup.enable && p.cgroup.delete != nil {
|
||||
err := p.cgroup.delete()
|
||||
if err != nil {
|
||||
@@ -131,13 +129,13 @@ func (p *ProcessBase) pInit() {
|
||||
log.Logger.Infow("创建进程成功")
|
||||
p.StopChan = make(chan struct{})
|
||||
p.State.manualStopFlag = false
|
||||
p.Pid = p.cmd.Process.Pid
|
||||
p.State.startTime = time.Now()
|
||||
p.ws = make(map[string]ConnectInstance)
|
||||
p.doOnInit()
|
||||
p.InitPerformanceStatus()
|
||||
p.initPsutil()
|
||||
p.initCgroup()
|
||||
p.Pid = p.p.Pid
|
||||
go p.watchDog()
|
||||
go p.readInit()
|
||||
go p.monitorHanler()
|
||||
@@ -263,83 +261,6 @@ func (p *ProcessBase) AddRecordTime() {
|
||||
p.performanceStatus.time = append(p.performanceStatus.time[1:], time.Now().Format(time.DateTime))
|
||||
}
|
||||
|
||||
func (p *ProcessBase) initCgroup() {
|
||||
if !p.Config.cgroupEnable {
|
||||
log.Logger.Debugw("不启用cgroup")
|
||||
return
|
||||
}
|
||||
switch cgroups.Mode() {
|
||||
case cgroups.Unavailable:
|
||||
log.Logger.Warnw("当前系统不支持cgroup")
|
||||
case cgroups.Legacy, cgroups.Hybrid:
|
||||
log.Logger.Debugw("启用cgroupv1")
|
||||
p.initCgroupV1()
|
||||
case cgroups.Unified:
|
||||
log.Logger.Debugw("启用cgroupv2")
|
||||
p.initCgroupV2()
|
||||
}
|
||||
}
|
||||
|
||||
func (p *ProcessBase) initCgroupV1() {
|
||||
resources := &specs.LinuxResources{}
|
||||
if p.Config.cpuLimit != nil {
|
||||
period := uint64(config.CF.CgroupPeriod)
|
||||
quota := int64(float32(config.CF.CgroupPeriod) * *p.Config.cpuLimit * 0.01)
|
||||
cpuResources := &specs.LinuxCPU{
|
||||
Period: &period,
|
||||
Quota: "a,
|
||||
}
|
||||
resources.CPU = cpuResources
|
||||
}
|
||||
if p.Config.memoryLimit != nil {
|
||||
limit := int64(*p.Config.memoryLimit * 1024 * 1024)
|
||||
memResources := &specs.LinuxMemory{
|
||||
Limit: &limit,
|
||||
}
|
||||
if config.CF.CgroupSwapLimit {
|
||||
memResources.Swap = &limit
|
||||
}
|
||||
resources.Memory = memResources
|
||||
}
|
||||
control, err := cgroup1.New(cgroup1.StaticPath("/"+p.Name), resources)
|
||||
if err != nil {
|
||||
log.Logger.Errorw("启用cgroup失败", "err", err, "name", p.Name)
|
||||
return
|
||||
}
|
||||
control.AddProc(uint64(p.cmd.Process.Pid))
|
||||
p.cgroup.delete = control.Delete
|
||||
p.cgroup.enable = true
|
||||
}
|
||||
|
||||
func (p *ProcessBase) initCgroupV2() {
|
||||
resources := &cgroup2.Resources{}
|
||||
if p.Config.cpuLimit != nil {
|
||||
period := uint64(config.CF.CgroupPeriod)
|
||||
quota := int64(float32(config.CF.CgroupPeriod) * *p.Config.cpuLimit * 0.01)
|
||||
resources.CPU = &cgroup2.CPU{
|
||||
Max: cgroup2.NewCPUMax("a, &period),
|
||||
}
|
||||
}
|
||||
if p.Config.memoryLimit != nil {
|
||||
limit := int64(*p.Config.memoryLimit * 1024 * 1024)
|
||||
memResources := &cgroup2.Memory{
|
||||
Max: &limit,
|
||||
}
|
||||
if config.CF.CgroupSwapLimit {
|
||||
memResources.Swap = &limit
|
||||
}
|
||||
resources.Memory = memResources
|
||||
}
|
||||
control, err := cgroup2.NewSystemd("/", p.Name+".slice", -1, resources)
|
||||
if err != nil {
|
||||
log.Logger.Errorw("启用cgroup失败", "err", err, "name", p.Name)
|
||||
return
|
||||
}
|
||||
control.AddProc(uint64(p.cmd.Process.Pid))
|
||||
p.cgroup.delete = control.DeleteSystemd
|
||||
p.cgroup.enable = true
|
||||
}
|
||||
|
||||
func (p *ProcessBase) monitorHanler() {
|
||||
if !p.monitor.enable {
|
||||
return
|
||||
@@ -389,7 +310,7 @@ func (p *ProcessBase) initPsutil() {
|
||||
}
|
||||
|
||||
func (p *ProcessBase) Kill() error {
|
||||
p.cmd.Process.Signal(syscall.SIGINT)
|
||||
p.p.Signal(syscall.SIGINT)
|
||||
select {
|
||||
case <-p.StopChan:
|
||||
{
|
||||
@@ -398,7 +319,7 @@ func (p *ProcessBase) Kill() error {
|
||||
case <-time.After(time.Second * time.Duration(config.CF.KillWaitTime)):
|
||||
{
|
||||
log.Logger.Debugw("进程kill超时,强制停止进程", "name", p.Name)
|
||||
return p.cmd.Process.Kill()
|
||||
return p.p.Kill()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
236
internal/app/service/process_pty_linux.go
Normal file
236
internal/app/service/process_pty_linux.go
Normal file
@@ -0,0 +1,236 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"os"
|
||||
"os/exec"
|
||||
"strings"
|
||||
|
||||
"github.com/containerd/cgroups/v3"
|
||||
"github.com/containerd/cgroups/v3/cgroup1"
|
||||
"github.com/containerd/cgroups/v3/cgroup2"
|
||||
"github.com/lzh-1625/go_process_manager/config"
|
||||
"github.com/lzh-1625/go_process_manager/internal/app/constants"
|
||||
"github.com/lzh-1625/go_process_manager/internal/app/model"
|
||||
"github.com/lzh-1625/go_process_manager/log"
|
||||
"github.com/lzh-1625/go_process_manager/utils"
|
||||
"github.com/opencontainers/runtime-spec/specs-go"
|
||||
|
||||
"github.com/creack/pty"
|
||||
)
|
||||
|
||||
type ProcessPty struct {
|
||||
*ProcessBase
|
||||
cacheBytesBuf *bytes.Buffer
|
||||
pty *os.File
|
||||
}
|
||||
|
||||
func (p *ProcessPty) doOnKilled() {
|
||||
p.pty.Close()
|
||||
}
|
||||
|
||||
func (p *ProcessPty) Type() constants.TerminalType {
|
||||
return constants.TERMINAL_PTY
|
||||
}
|
||||
|
||||
func (p *ProcessPty) Start() (err error) {
|
||||
defer func() {
|
||||
log.Logger.DeleteAdditionalInfo(1)
|
||||
if err != nil {
|
||||
p.Config.AutoRestart = false
|
||||
p.SetState(constants.PROCESS_WARNNING)
|
||||
p.State.Info = "进程启动失败:" + err.Error()
|
||||
}
|
||||
}()
|
||||
log.Logger.AddAdditionalInfo("进程名称", p.Name)
|
||||
if ok := p.SetState(constants.PROCESS_START, func() bool {
|
||||
return p.State.State != 1
|
||||
}); !ok {
|
||||
log.Logger.Warnw("进程已在运行,跳过启动")
|
||||
return nil
|
||||
}
|
||||
cmd := exec.Command(p.StartCommand[0], p.StartCommand[1:]...)
|
||||
cmd.Dir = p.WorkDir
|
||||
pf, err := pty.Start(cmd)
|
||||
if err != nil || cmd.Process == nil {
|
||||
log.Logger.Errorw("进程启动失败", "err", err)
|
||||
return err
|
||||
}
|
||||
pty.Setsize(pf, &pty.Winsize{
|
||||
Rows: 100,
|
||||
Cols: 100,
|
||||
})
|
||||
p.pty = pf
|
||||
log.Logger.Infow("进程启动成功", "进程名称", p.Name, "重启次数", p.State.restartTimes)
|
||||
p.p = cmd.Process
|
||||
p.pInit()
|
||||
p.push("进程启动成功")
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *ProcessPty) SetTerminalSize(cols, rows int) {
|
||||
if cols == 0 || rows == 0 || len(p.ws) != 0 {
|
||||
return
|
||||
}
|
||||
if err := pty.Setsize(p.pty, &pty.Winsize{
|
||||
Cols: uint16(cols),
|
||||
Rows: uint16(rows),
|
||||
}); err != nil {
|
||||
log.Logger.Error("设置终端尺寸失败", "err", err)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func (p *ProcessPty) WriteBytes(input []byte) (err error) {
|
||||
_, err = p.pty.Write(input)
|
||||
return
|
||||
}
|
||||
|
||||
func (p *ProcessPty) Write(input string) (err error) {
|
||||
_, err = p.pty.Write([]byte(input))
|
||||
return
|
||||
}
|
||||
|
||||
func (p *ProcessPty) readInit() {
|
||||
log.Logger.Debugw("stdout读取线程已启动", "进程名", p.Name, "使用者", p.GetUserString())
|
||||
buf := make([]byte, 1024)
|
||||
for {
|
||||
select {
|
||||
case <-p.StopChan:
|
||||
{
|
||||
log.Logger.Debugw("stdout读取线程已退出", "进程名", p.Name, "使用者", p.GetUserString())
|
||||
return
|
||||
}
|
||||
default:
|
||||
{
|
||||
n, _ := p.pty.Read(buf)
|
||||
p.bufHanle(buf[:n])
|
||||
if len(p.ws) == 0 {
|
||||
continue
|
||||
}
|
||||
p.wsLock.Lock()
|
||||
for _, v := range p.ws {
|
||||
v.Write(buf[:n])
|
||||
}
|
||||
p.wsLock.Unlock()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (p *ProcessPty) initCgroup() {
|
||||
if !p.Config.cgroupEnable {
|
||||
log.Logger.Debugw("不启用cgroup")
|
||||
return
|
||||
}
|
||||
switch cgroups.Mode() {
|
||||
case cgroups.Unavailable:
|
||||
log.Logger.Warnw("当前系统不支持cgroup")
|
||||
case cgroups.Legacy, cgroups.Hybrid:
|
||||
log.Logger.Debugw("启用cgroupv1")
|
||||
p.initCgroupV1()
|
||||
case cgroups.Unified:
|
||||
log.Logger.Debugw("启用cgroupv2")
|
||||
p.initCgroupV2()
|
||||
}
|
||||
}
|
||||
|
||||
func (p *ProcessPty) initCgroupV1() {
|
||||
resources := &specs.LinuxResources{}
|
||||
if p.Config.cpuLimit != nil {
|
||||
period := uint64(config.CF.CgroupPeriod)
|
||||
quota := int64(float32(config.CF.CgroupPeriod) * *p.Config.cpuLimit * 0.01)
|
||||
cpuResources := &specs.LinuxCPU{
|
||||
Period: &period,
|
||||
Quota: "a,
|
||||
}
|
||||
resources.CPU = cpuResources
|
||||
}
|
||||
if p.Config.memoryLimit != nil {
|
||||
limit := int64(*p.Config.memoryLimit * 1024 * 1024)
|
||||
memResources := &specs.LinuxMemory{
|
||||
Limit: &limit,
|
||||
}
|
||||
if config.CF.CgroupSwapLimit {
|
||||
memResources.Swap = &limit
|
||||
}
|
||||
resources.Memory = memResources
|
||||
}
|
||||
control, err := cgroup1.New(cgroup1.StaticPath("/"+p.Name), resources)
|
||||
if err != nil {
|
||||
log.Logger.Errorw("启用cgroup失败", "err", err, "name", p.Name)
|
||||
return
|
||||
}
|
||||
control.AddProc(uint64(p.Pid))
|
||||
p.cgroup.delete = control.Delete
|
||||
p.cgroup.enable = true
|
||||
}
|
||||
|
||||
func (p *ProcessPty) initCgroupV2() {
|
||||
resources := &cgroup2.Resources{}
|
||||
if p.Config.cpuLimit != nil {
|
||||
period := uint64(config.CF.CgroupPeriod)
|
||||
quota := int64(float32(config.CF.CgroupPeriod) * *p.Config.cpuLimit * 0.01)
|
||||
resources.CPU = &cgroup2.CPU{
|
||||
Max: cgroup2.NewCPUMax("a, &period),
|
||||
}
|
||||
}
|
||||
if p.Config.memoryLimit != nil {
|
||||
limit := int64(*p.Config.memoryLimit * 1024 * 1024)
|
||||
memResources := &cgroup2.Memory{
|
||||
Max: &limit,
|
||||
}
|
||||
if config.CF.CgroupSwapLimit {
|
||||
memResources.Swap = &limit
|
||||
}
|
||||
resources.Memory = memResources
|
||||
}
|
||||
control, err := cgroup2.NewSystemd("/", p.Name+".slice", -1, resources)
|
||||
if err != nil {
|
||||
log.Logger.Errorw("启用cgroup失败", "err", err, "name", p.Name)
|
||||
return
|
||||
}
|
||||
control.AddProc(uint64(p.Pid))
|
||||
p.cgroup.delete = control.DeleteSystemd
|
||||
p.cgroup.enable = true
|
||||
}
|
||||
|
||||
func (p *ProcessPty) ReadCache(ws ConnectInstance) {
|
||||
ws.Write(p.cacheBytesBuf.Bytes())
|
||||
}
|
||||
|
||||
func (p *ProcessPty) bufHanle(b []byte) {
|
||||
log := strings.TrimSpace(string(b))
|
||||
if utils.RemoveANSI(log) != "" {
|
||||
p.logReportHandler(log)
|
||||
}
|
||||
p.cacheBytesBuf.Write(b)
|
||||
p.cacheBytesBuf.Next(len(b))
|
||||
}
|
||||
|
||||
func (p *ProcessPty) doOnInit() {
|
||||
p.cacheBytesBuf = bytes.NewBuffer(make([]byte, config.CF.ProcessMsgCacheBufLimit))
|
||||
|
||||
}
|
||||
|
||||
func NewProcessPty(pconfig model.Process) *ProcessBase {
|
||||
p := ProcessBase{
|
||||
Name: pconfig.Name,
|
||||
StartCommand: strings.Split(pconfig.Cmd, " "),
|
||||
WorkDir: pconfig.Cwd,
|
||||
}
|
||||
processPty := ProcessPty{
|
||||
ProcessBase: &p,
|
||||
}
|
||||
p.Process = &processPty
|
||||
processPty.setProcessConfig(pconfig)
|
||||
return &p
|
||||
}
|
||||
|
||||
func RunNewProcessPty(pconfig model.Process) (*ProcessBase, error) {
|
||||
processPty := NewProcessPty(pconfig)
|
||||
if err := processPty.Start(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return processPty, nil
|
||||
}
|
@@ -3,7 +3,6 @@ package service
|
||||
import (
|
||||
"bytes"
|
||||
"os"
|
||||
"os/exec"
|
||||
"strings"
|
||||
|
||||
"github.com/lzh-1625/go_process_manager/config"
|
||||
@@ -12,13 +11,13 @@ import (
|
||||
"github.com/lzh-1625/go_process_manager/log"
|
||||
"github.com/lzh-1625/go_process_manager/utils"
|
||||
|
||||
"github.com/creack/pty"
|
||||
"github.com/runletapp/go-console"
|
||||
)
|
||||
|
||||
type ProcessPty struct {
|
||||
*ProcessBase
|
||||
cacheBytesBuf *bytes.Buffer
|
||||
pty *os.File
|
||||
pty console.Console
|
||||
}
|
||||
|
||||
func (p *ProcessPty) doOnKilled() {
|
||||
@@ -45,20 +44,29 @@ func (p *ProcessPty) Start() (err error) {
|
||||
log.Logger.Warnw("进程已在运行,跳过启动")
|
||||
return nil
|
||||
}
|
||||
cmd := exec.Command(p.StartCommand[0], p.StartCommand[1:]...)
|
||||
cmd.Dir = p.WorkDir
|
||||
pf, err := pty.Start(cmd)
|
||||
if err != nil || cmd.Process == nil {
|
||||
pty, err := console.New(100, 100)
|
||||
if err != nil {
|
||||
log.Logger.Errorw("进程启动失败", "err", err)
|
||||
return err
|
||||
}
|
||||
pty.SetCWD(p.WorkDir)
|
||||
err = pty.Start(p.StartCommand)
|
||||
if err != nil {
|
||||
log.Logger.Errorw("进程启动失败", "err", err)
|
||||
return err
|
||||
}
|
||||
p.pty = pty
|
||||
pid, err := pty.Pid()
|
||||
if err != nil {
|
||||
log.Logger.Errorw("进程启动失败", "err", err)
|
||||
return err
|
||||
}
|
||||
p.p, err = os.FindProcess(pid)
|
||||
if err != nil {
|
||||
log.Logger.Errorw("进程启动失败", "err", err)
|
||||
return err
|
||||
}
|
||||
pty.Setsize(pf, &pty.Winsize{
|
||||
Rows: 100,
|
||||
Cols: 100,
|
||||
})
|
||||
p.pty = pf
|
||||
log.Logger.Infow("进程启动成功", "进程名称", p.Name, "重启次数", p.State.restartTimes)
|
||||
p.cmd = cmd
|
||||
p.pInit()
|
||||
p.push("进程启动成功")
|
||||
return nil
|
||||
@@ -68,12 +76,7 @@ func (p *ProcessPty) SetTerminalSize(cols, rows int) {
|
||||
if cols == 0 || rows == 0 || len(p.ws) != 0 {
|
||||
return
|
||||
}
|
||||
if err := pty.Setsize(p.pty, &pty.Winsize{
|
||||
Cols: uint16(cols),
|
||||
Rows: uint16(rows),
|
||||
}); err != nil {
|
||||
log.Logger.Error("设置终端尺寸失败", "err", err)
|
||||
}
|
||||
p.pty.SetSize(cols, rows)
|
||||
|
||||
}
|
||||
|
||||
@@ -114,6 +117,10 @@ func (p *ProcessPty) readInit() {
|
||||
}
|
||||
}
|
||||
|
||||
func (p *ProcessPty) initCgroup() {
|
||||
log.Logger.Debugw("不支持cgroup")
|
||||
}
|
||||
|
||||
func (p *ProcessPty) ReadCache(ws ConnectInstance) {
|
||||
ws.Write(p.cacheBytesBuf.Bytes())
|
||||
}
|
||||
@@ -129,6 +136,7 @@ func (p *ProcessPty) bufHanle(b []byte) {
|
||||
|
||||
func (p *ProcessPty) doOnInit() {
|
||||
p.cacheBytesBuf = bytes.NewBuffer(make([]byte, config.CF.ProcessMsgCacheBufLimit))
|
||||
p.ProcessBase.Pid = utils.UnwarpIgnore(p.pty.Pid())
|
||||
}
|
||||
|
||||
func NewProcessPty(pconfig model.Process) *ProcessBase {
|
@@ -72,7 +72,7 @@ func (p *ProcessStd) Start() (err error) {
|
||||
return err
|
||||
}
|
||||
log.Logger.Infow("进程启动成功", "重启次数", p.State.restartTimes)
|
||||
p.cmd = cmd
|
||||
p.p = cmd.Process
|
||||
p.pInit()
|
||||
p.push("进程启动成功")
|
||||
return nil
|
||||
@@ -82,6 +82,10 @@ func (p *ProcessStd) doOnInit() {
|
||||
p.cacheLine = make([]string, config.CF.ProcessMsgCacheLinesLimit)
|
||||
}
|
||||
|
||||
func (p *ProcessStd) initCgroup() {
|
||||
log.Logger.Debugw("不支持cgroup")
|
||||
}
|
||||
|
||||
func (p *ProcessStd) ReadCache(ws ConnectInstance) {
|
||||
for _, line := range p.cacheLine {
|
||||
ws.WriteString(line)
|
||||
|
Reference in New Issue
Block a user