mirror of
https://github.com/lzh-1625/go_process_manager.git
synced 2025-10-05 16:06:51 +08:00
初次提交
This commit is contained in:
182
service/process/process_std.go
Normal file
182
service/process/process_std.go
Normal file
@@ -0,0 +1,182 @@
|
||||
package process
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"io"
|
||||
"msm/config"
|
||||
"msm/log"
|
||||
"msm/model"
|
||||
"os/exec"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/gorilla/websocket"
|
||||
)
|
||||
|
||||
type ProcessStd struct {
|
||||
ProcessBase
|
||||
cacheLine []string
|
||||
stdin io.WriteCloser
|
||||
stdout *bufio.Scanner
|
||||
}
|
||||
|
||||
func (p *ProcessStd) Kill() error {
|
||||
return p.cmd.Process.Kill()
|
||||
}
|
||||
|
||||
func (p *ProcessStd) watchDog() {
|
||||
state, _ := p.cmd.Process.Wait()
|
||||
close(p.stopChan)
|
||||
p.State.State = 0
|
||||
if state.ExitCode() != 0 {
|
||||
log.Logger.Infow("进程停止", "进程名称", p.Name, "exitCode", state.ExitCode(), "进程类型", "std")
|
||||
p.push(fmt.Sprintf("进程停止,退出码 %d", state.ExitCode()))
|
||||
if p.Config.AutoRestart {
|
||||
p.ReStart()
|
||||
}
|
||||
} else {
|
||||
log.Logger.Infow("进程正常退出", "进程名称", p.Name)
|
||||
p.push("进程正常退出")
|
||||
}
|
||||
}
|
||||
|
||||
func (p *ProcessStd) WriteBytes(input []byte) (err error) {
|
||||
p.logReportHandler(config.CF.ProcessInputPrefix + string(input))
|
||||
_, err = p.stdin.Write(append(input, '\n'))
|
||||
return
|
||||
}
|
||||
|
||||
func (p *ProcessStd) Write(input string) (err error) {
|
||||
p.logReportHandler(config.CF.ProcessInputPrefix + input)
|
||||
_, err = p.stdin.Write([]byte(input + "\n"))
|
||||
return
|
||||
}
|
||||
|
||||
func (p *ProcessStd) ReStart() {
|
||||
if p.State.restartTimes > config.CF.ProcessRestartsLimit {
|
||||
log.Logger.Warnw("重启次数达到上限", "name", p.Name, "limit", config.CF.ProcessRestartsLimit)
|
||||
p.State.State = 2
|
||||
p.State.Info = "重启次数异常"
|
||||
p.push("进程重启次数达到上限")
|
||||
return
|
||||
}
|
||||
cmd := exec.Command(p.StartCommand[0], p.StartCommand[1:]...) // 替换为你要执行的命令及参数
|
||||
cmd.Dir = p.cmd.Dir
|
||||
out, err := cmd.StdoutPipe()
|
||||
if err != nil {
|
||||
log.Logger.Errorw("重启失败,输出管道获取失败", "err", err)
|
||||
p.Config.AutoRestart = false
|
||||
return
|
||||
}
|
||||
p.stdout = bufio.NewScanner(out)
|
||||
p.stdin, err = cmd.StdinPipe()
|
||||
if err != nil {
|
||||
log.Logger.Errorw("重启失败,输入管道获取失败", "err", err)
|
||||
p.Config.AutoRestart = false
|
||||
return
|
||||
}
|
||||
err = cmd.Start()
|
||||
if err != nil {
|
||||
log.Logger.Errorw("重启失败,进程启动出错:", "err", err)
|
||||
p.Config.AutoRestart = false
|
||||
return
|
||||
}
|
||||
p.State.restartTimes++
|
||||
log.Logger.Infow("进程启动成功", "进程名称", p.Name, "重启次数", p.State.restartTimes)
|
||||
p.cmd = cmd
|
||||
p.pInit()
|
||||
p.push("进程启动成功")
|
||||
|
||||
}
|
||||
|
||||
func (p *ProcessStd) pInit() {
|
||||
log.Logger.Infow("创建进程成功")
|
||||
p.Control.changControlChan = make(chan int)
|
||||
p.stopChan = make(chan struct{})
|
||||
p.State.State = 1
|
||||
p.Pid = p.cmd.Process.Pid
|
||||
p.State.startTime = time.Now()
|
||||
p.cacheLine = make([]string, config.CF.ProcessMsgCacheLinesLimit)
|
||||
p.InitPerformanceStatus()
|
||||
p.initPsutil()
|
||||
go p.watchDog()
|
||||
go p.readInit()
|
||||
go p.monitorHanler()
|
||||
}
|
||||
|
||||
func (p *ProcessStd) ReadCache(ws *websocket.Conn) {
|
||||
for _, line := range p.cacheLine {
|
||||
ws.WriteMessage(websocket.TextMessage, []byte(line))
|
||||
}
|
||||
}
|
||||
|
||||
func (p *ProcessStd) readInit() {
|
||||
var output string
|
||||
log.Logger.Debugw("stdout读取线程已启动", "进程名", p.Name, "使用者", p.WhoUsing)
|
||||
for {
|
||||
select {
|
||||
case <-p.stopChan:
|
||||
{
|
||||
p.IsUsing.Store(false)
|
||||
p.WhoUsing = ""
|
||||
log.Logger.Debugw("stdout读取线程已退出", "进程名", p.Name, "使用者", p.WhoUsing)
|
||||
return
|
||||
}
|
||||
default:
|
||||
{
|
||||
output = p.Read()
|
||||
if p.IsUsing.Load() && output != "" {
|
||||
p.ws.wsMux.Lock()
|
||||
p.ws.wsConnect.WriteMessage(websocket.TextMessage, []byte(output))
|
||||
p.ws.wsMux.Unlock()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
func (p *ProcessStd) Read() string {
|
||||
if p.stdout.Scan() {
|
||||
output := p.stdout.Text()
|
||||
p.logReportHandler(output)
|
||||
p.cacheLine = p.cacheLine[1:]
|
||||
p.cacheLine = append(p.cacheLine, output)
|
||||
return output
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func RunNewProcessStd(pconfig model.Process) (*ProcessStd, error) {
|
||||
args := strings.Split(pconfig.Cmd, " ")
|
||||
cmd := exec.Command(args[0], args[1:]...) // 替换为你要执行的命令及参数
|
||||
|
||||
processStd := ProcessStd{
|
||||
ProcessBase: ProcessBase{
|
||||
Name: pconfig.Name,
|
||||
StartCommand: args,
|
||||
},
|
||||
}
|
||||
cmd.Dir = pconfig.Cwd
|
||||
out, err := cmd.StdoutPipe()
|
||||
if err != nil {
|
||||
log.Logger.Errorw("输出管道获取失败", "err", err)
|
||||
return nil, err
|
||||
}
|
||||
processStd.stdout = bufio.NewScanner(out)
|
||||
processStd.stdin, err = cmd.StdinPipe()
|
||||
if err != nil {
|
||||
log.Logger.Errorw("输入管道获取失败", "err", err)
|
||||
return nil, err
|
||||
}
|
||||
err = cmd.Start()
|
||||
if err != nil || cmd.Process == nil {
|
||||
log.Logger.Error("进程启动出错:", err)
|
||||
return nil, err
|
||||
}
|
||||
log.Logger.Infow("创建进程成功", "config", pconfig)
|
||||
processStd.cmd = cmd
|
||||
processStd.SetTermType("std")
|
||||
processStd.pInit()
|
||||
processStd.setProcessConfig(pconfig)
|
||||
return &processStd, nil
|
||||
}
|
Reference in New Issue
Block a user