mirror of
https://github.com/lzh-1625/go_process_manager.git
synced 2025-10-04 15:42:44 +08:00
154 lines
3.1 KiB
Go
154 lines
3.1 KiB
Go
package termui
|
|
|
|
import (
|
|
"context"
|
|
"os"
|
|
"time"
|
|
|
|
"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/logic"
|
|
"github.com/lzh-1625/go_process_manager/log"
|
|
"github.com/lzh-1625/go_process_manager/utils"
|
|
|
|
"github.com/rivo/tview"
|
|
)
|
|
|
|
type TermConnectInstance struct {
|
|
CancelFunc context.CancelFunc
|
|
}
|
|
|
|
func (t *TermConnectInstance) Write(b []byte) {
|
|
os.Stdout.Write(b)
|
|
}
|
|
func (t *TermConnectInstance) WriteString(s string) {
|
|
os.Stdout.Write([]byte(s))
|
|
|
|
}
|
|
func (t *TermConnectInstance) Cancel() {
|
|
t.CancelFunc()
|
|
}
|
|
|
|
type tui struct {
|
|
app *tview.Application
|
|
}
|
|
|
|
var Tui = new(tui)
|
|
|
|
func (t *tui) TermuiInit() {
|
|
if config.CF.Tui {
|
|
t.drawProcessList()
|
|
}
|
|
}
|
|
|
|
func (t *tui) drawProcessList() {
|
|
t.app = tview.NewApplication()
|
|
list := tview.NewList()
|
|
for i, v := range logic.ProcessCtlLogic.GetProcessList() {
|
|
if i >= 'r' {
|
|
i++
|
|
}
|
|
list.AddItem(v.Name, utils.NewKVStr().Add("user_name", v.User).Add("start_time", v.StartTime).Add("state", v.State.State).Build(), 'a'+rune(i), func() {
|
|
if v.State.State != 1 || v.TermType != eum.TerminalPty {
|
|
return
|
|
}
|
|
t.teminal(v.Uuid)
|
|
t.app.Stop()
|
|
t.drawProcessList()
|
|
})
|
|
}
|
|
list.AddItem("Refresh", "refresh process list", 'r', func() {
|
|
t.app.Stop()
|
|
t.drawProcessList()
|
|
})
|
|
if err := t.app.SetRoot(list, true).SetFocus(list).Run(); err != nil {
|
|
panic(err)
|
|
}
|
|
}
|
|
|
|
func (t *tui) teminal(uuid int) {
|
|
p, err := logic.ProcessCtlLogic.GetProcess(uuid)
|
|
if err != nil {
|
|
log.Logger.Error("不存在uuid", "uuid", uuid)
|
|
}
|
|
ctx, cancel := context.WithCancel(context.Background())
|
|
tci := &TermConnectInstance{
|
|
CancelFunc: cancel,
|
|
}
|
|
p.AddConn(eum.Console, tci)
|
|
defer p.DeleteConn(eum.Console)
|
|
os.Stdin.Write([]byte("\033[H\033[2J")) // 清空屏幕
|
|
p.ReadCache(tci)
|
|
go t.startConnect(p, ctx, cancel)
|
|
log.Logger.Info("tui wait")
|
|
select {
|
|
case <-p.StopChan:
|
|
case <-time.After(time.Minute * 10):
|
|
case <-ctx.Done():
|
|
}
|
|
log.Logger.Info("tui quit")
|
|
}
|
|
|
|
func (t *tui) startConnect(p logic.Process, ctx context.Context, cancel context.CancelFunc) {
|
|
switch p.Type() {
|
|
case eum.TerminalPty:
|
|
{
|
|
t.ptyConnect(p, ctx, cancel)
|
|
}
|
|
case eum.TerminalStd:
|
|
{
|
|
t.stdConnect(p, ctx, cancel)
|
|
}
|
|
}
|
|
}
|
|
|
|
func (t *tui) ptyConnect(p logic.Process, ctx context.Context, cancel context.CancelFunc) {
|
|
buf := make([]byte, 1024)
|
|
for {
|
|
select {
|
|
case <-ctx.Done():
|
|
return
|
|
default:
|
|
{
|
|
n, err := os.Stdin.Read(buf)
|
|
if err != nil {
|
|
return
|
|
}
|
|
if buf[0] == 0x04 { // ctrl+d 信号
|
|
cancel()
|
|
continue
|
|
}
|
|
p.WriteBytes(buf[:n])
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func (t *tui) stdConnect(p logic.Process, ctx context.Context, cancel context.CancelFunc) {
|
|
buf := make([]byte, 1024)
|
|
var line string
|
|
for {
|
|
select {
|
|
case <-ctx.Done():
|
|
return
|
|
default:
|
|
{
|
|
n, err := os.Stdin.Read(buf)
|
|
if err != nil {
|
|
return
|
|
}
|
|
if buf[0] == 0x04 { // ctrl+d 信号
|
|
cancel()
|
|
continue
|
|
}
|
|
if buf[0] == 0x13 { // enter 信号
|
|
p.Write(line)
|
|
line = ""
|
|
continue
|
|
}
|
|
line += string(buf[:n])
|
|
}
|
|
}
|
|
}
|
|
}
|