1
0
forked from x/icebergs
This commit is contained in:
shaoying 2020-06-25 18:36:08 +08:00
parent 42fbc992a1
commit b368ff0cfb
10 changed files with 448 additions and 342 deletions

View File

@ -49,8 +49,9 @@ var Index = &ice.Context{Name: "cli", Help: "命令模块",
m.Conf(RUNTIME, "host.pid", os.Getpid())
// 启动信息
if user, e := user.Current(); e == nil {
m.Conf(RUNTIME, "boot.username", path.Base(kit.Select(user.Name, os.Getenv("USER"))))
m.Conf(RUNTIME, "boot.username", os.Getenv("USER"))
if user, e := user.Current(); e == nil && user.Name != "" {
m.Conf(RUNTIME, "boot.username", user.Name)
}
if name, e := os.Hostname(); e == nil {
m.Conf(RUNTIME, "boot.hostname", kit.Select(name, os.Getenv("HOSTNAME")))

View File

@ -61,7 +61,7 @@ func (f *Frame) Start(m *ice.Message, arg ...string) bool {
// 异步事件
m.Logs(EVENT, d[0], d[1:])
m.Grows(EVENT, d[0], "", "", func(index int, value map[string]interface{}) {
m.Cmd(value["cmd"], d[1:]).Cost("event %v", d)
m.Cmd(value["cmd"], d).Cost("event %v", d)
})
}
}
@ -86,6 +86,23 @@ const (
MISS_CREATE = "miss.create"
MIND_CREATE = "mind.create"
)
const (
INIT = "init"
AUTO = "auto"
MAKE = "make"
OPEN = "open"
CLOSE = "close"
START = "start"
STOP = "stop"
RESTART = "restart"
CHANGE = "change"
PRUNE = "prune"
CLEAR = "clear"
)
const (
LISTEN = "listen"
ACTION = "action"

View File

@ -4,6 +4,7 @@ import (
ice "github.com/shylinux/icebergs"
"github.com/shylinux/icebergs/base/cli"
"github.com/shylinux/icebergs/base/gdb"
"github.com/shylinux/icebergs/base/mdb"
"github.com/shylinux/icebergs/base/nfs"
kit "github.com/shylinux/toolkits"
@ -18,10 +19,13 @@ func _dream_list(m *ice.Message) {
m.Cmdy(nfs.DIR, m.Conf(DREAM, "meta.path"), "time name").Table(func(index int, value map[string]string, head []string) {
if m.Richs(SPACE, nil, value[kit.MDB_NAME], func(key string, value map[string]interface{}) {
m.Push(kit.MDB_TYPE, value[kit.MDB_TYPE])
m.Push(kit.MDB_STATUS, "start")
m.Push(kit.MDB_STATUS, gdb.START)
}) == nil {
m.Push(kit.MDB_TYPE, "none")
m.Push(kit.MDB_STATUS, "stop")
m.Push(kit.MDB_STATUS, gdb.STOP)
}
for _, k := range []string{"start", "stop", "restart"} {
m.Push(k, m.Cmdx(mdb.RENDER, RENDER.Button, k))
}
})
m.Sort(kit.MDB_NAME)
@ -34,52 +38,96 @@ func _dream_show(m *ice.Message, name string) {
// 创建目录
p := path.Join(m.Conf(DREAM, "meta.path"), name)
os.MkdirAll(p, 0777)
os.MkdirAll(p, ice.MOD_DIR)
miss := path.Join(p, "etc/miss.sh")
if _, e := os.Stat(miss); e != nil {
m.Cmd(nfs.SAVE, miss, m.Conf(DREAM, "meta.miss"))
}
if b, e := ioutil.ReadFile(path.Join(p, m.Conf(gdb.SIGNAL, "meta.pid"))); e == nil {
if s, e := os.Stat("/proc/" + string(b)); e == nil && s.IsDir() {
m.Info("already exists %v", string(b))
// 已经启动
return
}
}
if m.Richs(SPACE, nil, name, nil) == nil {
// 启动任务
m.Option(cli.CMD_TYPE, "daemon")
m.Option(cli.CMD_DIR, p)
m.Optionv(cli.CMD_ENV,
m.Option(cli.CMD_STDERR, path.Join(p, m.Conf(DREAM, "meta.env.ctx_log")))
m.Optionv(cli.CMD_ENV, kit.Simple(
"ctx_dev", m.Conf(cli.RUNTIME, "conf.ctx_dev"),
"ctx_log", "boot.log", "ctx_mod", "ctx,log,gdb,ssh",
"PATH", kit.Path(path.Join(p, "bin"))+":"+os.Getenv("PATH"),
)
m.Cmd(m.Confv(DREAM, "meta.cmd"), "self", name)
"USER", cli.UserName,
m.Confv(DREAM, "meta.env"),
))
m.Cmd(cli.DAEMON, m.Confv(DREAM, "meta.cmd"), "self", name)
}
m.Cmdy(nfs.DIR, p)
}
const DREAM = "dream"
const (
DREAM_START = "dream.start"
DREAM_STOP = "dream.stop"
)
func init() {
Index.Merge(&ice.Context{
Configs: map[string]*ice.Config{
DREAM: {Name: "dream", Help: "梦想家", Value: kit.Data("path", "usr/local/work",
// "cmd", []interface{}{cli.SYSTEM, "ice.sh", "start", ice.WEB_SPACE, "connect"},
"cmd", []interface{}{cli.SYSTEM, "ice.bin", SPACE, "connect"},
"cmd", []interface{}{"ice.bin", SPACE, "connect"}, "env", kit.Dict(
"ctx_log", "bin/boot.log", "ctx_mod", "ctx,log,gdb,ssh",
),
"miss", `#!/bin/bash
git &>/dev/null || yum install -y git
[ -f ~/.ish/plug.sh ] || [ -f ./.ish/plug.sh ] || git clone https://github.com/shylinux/intshell ./.ish
[ "$ISH_CONF_PRE" != "" ] || source ./.ish/plug.sh || source ~/.ish/plug.sh
# declare -f ish_help_repos &>/dev/null || require conf.sh
require show.sh
require help.sh
require miss.sh
ish_miss_prepare_volcanos
# ish_miss_prepare_icebergs
# ish_miss_prepare toolkits
# ish_miss_prepare_intshell
# ish_miss_prepare learning
go &>/dev/null || yum install -y golang
ish_miss_prepare_compile
ish_miss_prepare_install
make || yum install -y make
`,
)},
},
Commands: map[string]*ice.Command{
DREAM: {Name: "dream [name] auto", Help: "梦想家", Meta: kit.Dict("detail", []interface{}{"启动", "停止"}), Action: map[string]*ice.Action{
"start": {Name: "start", Help: "启动", Hand: func(m *ice.Message, arg ...string) {
DREAM: {Name: "dream [name [cmd...]] auto", Help: "梦想家", Meta: kit.Dict("detail", []interface{}{"启动", "停止"}), Action: map[string]*ice.Action{
gdb.START: {Name: "start", Help: "启动", Hand: func(m *ice.Message, arg ...string) {
_dream_show(m, m.Option(kit.MDB_NAME))
}},
"stop": {Name: "stop", Help: "停止", Hand: func(m *ice.Message, arg ...string) {
m.Cmd(SPACE, m.Option("name"), "exit", "1")
gdb.STOP: {Name: "stop", Help: "停止", Hand: func(m *ice.Message, arg ...string) {
m.Cmd(SPACE, m.Option(kit.MDB_NAME), "exit", "1")
}},
gdb.RESTART: {Name: "restart", Help: "重启", Hand: func(m *ice.Message, arg ...string) {
m.Cmd(SPACE, m.Option(kit.MDB_NAME), "exit", "1")
m.Sleep("1s")
_dream_show(m, m.Option(kit.MDB_NAME))
}},
}, Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
if len(arg) == 0 {
_dream_list(m)
return
}
if len(arg) > 1 {
m.Cmdy(SPACE, arg[0], arg[1:])
return
}
_dream_show(m, arg[0])
}},
},

View File

@ -236,10 +236,16 @@ func init() {
task.Put(name, func(task *task.Task) error {
// 监听消息
m.Event(gdb.SPACE_START, WORKER, name)
switch kind {
case WORKER:
m.Event(DREAM_START, name)
defer m.Event(DREAM_STOP, name)
default:
m.Event(gdb.SPACE_START, kind, name)
defer m.Event(gdb.SPACE_CLOSE, kind, name)
}
_space_handle(m, false, m.Target().Server().(*Frame).send, s, name)
m.Log(ice.LOG_CLOSE, "%s: %s", name, kit.Format(m.Confv(SPACE, kit.Keys(kit.MDB_HASH, h))))
m.Event(gdb.SPACE_CLOSE, WORKER, name)
m.Confv(SPACE, kit.Keys(kit.MDB_HASH, h), "")
return nil
})

View File

@ -8,6 +8,9 @@ import (
"strings"
)
var ErrWarn = "warn: "
var ErrNotFound = "not found "
func (m *Message) log(level string, str string, arg ...interface{}) *Message {
if str = strings.TrimSpace(fmt.Sprintf(str, arg...)); Log != nil {
// 日志模块
@ -33,7 +36,8 @@ func (m *Message) log(level string, str string, arg ...interface{}) *Message {
// 文件行号
switch level {
case LOG_CMDS, LOG_INFO, LOG_WARN, "refer", "form":
// case LOG_CMDS, LOG_INFO, LOG_WARN, "refer", "form":
case LOG_CMDS, LOG_INFO, "refer", "form":
case "register", "begin":
default:
suffix += " " + kit.FileLine(3, 2)
@ -60,7 +64,7 @@ func (m *Message) Info(str string, arg ...interface{}) *Message {
}
func (m *Message) Warn(err bool, arg ...interface{}) bool {
if err {
m.meta[MSG_RESULT] = append([]string{"warn: "}, kit.Simple(arg...)...)
m.meta[MSG_RESULT] = append([]string{ErrWarn}, kit.Simple(arg...)...)
return m.log(LOG_WARN, fmt.Sprint(arg...)) != nil
}
return false

12
meta.go
View File

@ -357,11 +357,15 @@ func (m *Message) Parse(meta string, key string, arg ...string) *Message {
}
func (m *Message) Split(str string, field string, space string, enter string) *Message {
indexs := []int{}
fields := kit.Split(field, space, "{}")
for i, l := range kit.Split(str, enter, "{}") {
fields := kit.Split(field, space, space, space)
for i, l := range kit.Split(str, enter, enter, enter) {
m.Debug("----%v----", l)
if strings.TrimSpace(l) == "" {
continue
}
if i == 0 && (field == "" || field == "index") {
// 表头行
fields = kit.Split(l, space)
fields = kit.Split(l, space, space)
if field == "index" {
for _, v := range fields {
indexs = append(indexs, strings.Index(l, v))
@ -382,7 +386,7 @@ func (m *Message) Split(str string, field string, space string, enter string) *M
continue
}
for i, v := range kit.Split(l, space) {
for i, v := range kit.Split(l, space, space) {
m.Push(kit.Select("some", fields, i), v)
}
}

View File

@ -28,6 +28,9 @@ func (m *Message) Load(arg ...string) *Message {
}
func (m *Message) Watch(key string, arg ...string) *Message {
if len(arg) == 0 {
arg = append(arg, m.Prefix("auto"))
}
m.Cmd("gdb.event", "listen", key, arg)
return m
}

View File

@ -5,10 +5,13 @@ import (
"github.com/shylinux/icebergs/base/cli"
"github.com/shylinux/icebergs/base/gdb"
"github.com/shylinux/icebergs/base/mdb"
"github.com/shylinux/icebergs/base/nfs"
"github.com/shylinux/icebergs/base/web"
"github.com/shylinux/icebergs/core/code"
kit "github.com/shylinux/toolkits"
"os"
"path"
"strings"
)
@ -16,85 +19,101 @@ const DOCKER = "docker"
const (
IMAGE = "image"
CONTAINER = "container"
COMMAND = "command"
)
var _docker = []string{cli.SYSTEM, DOCKER}
var _image = []string{cli.SYSTEM, DOCKER, IMAGE}
var _container = []string{cli.SYSTEM, DOCKER, CONTAINER}
var Index = &ice.Context{Name: "docker", Help: "虚拟机",
Caches: map[string]*ice.Cache{},
Configs: map[string]*ice.Config{
DOCKER: {Name: "docker", Help: "虚拟机", Value: kit.Data(
kit.MDB_SHORT, "name", "build", []interface{}{}),
},
"repos", "centos", "build", []interface{}{"home", "mount"},
)},
},
Commands: map[string]*ice.Command{
IMAGE: {Name: "image", Help: "镜像管理", Meta: kit.Dict("detail", []string{"运行", "清理", "删除"}), List: ListLook("IMAGE_ID"), Action: map[string]*ice.Action{
IMAGE: {Name: "image IMAGE_ID=auto auto", Help: "镜像管理", Meta: kit.Dict(
"detail", []string{"运行", "清理", "删除"},
), Action: map[string]*ice.Action{
"run": {Name: "run", Help: "运行", Hand: func(m *ice.Message, arg ...string) {
m.Cmdy(cli.SYSTEM, DOCKER, "run", "-dt", m.Option("REPOSITORY")+":"+m.Option("TAG"))
m.Cmdy(_docker, "run", "-dt", m.Option("REPOSITORY")+":"+m.Option("TAG"))
}},
"prune": {Name: "prune", Help: "清理", Hand: func(m *ice.Message, arg ...string) {
m.Cmdy(cli.SYSTEM, DOCKER, "prune", "-f")
gdb.PRUNE: {Name: "prune", Help: "清理", Hand: func(m *ice.Message, arg ...string) {
m.Cmdy(_image, "prune", "-f")
}},
mdb.DELETE: {Name: "delete", Help: "删除", Hand: func(m *ice.Message, arg ...string) {
m.Cmdy(cli.SYSTEM, DOCKER, "rm", m.Option("IMAGE_ID"))
gdb.CLEAR: {Name: "clear", Help: "删除", Hand: func(m *ice.Message, arg ...string) {
m.Cmdy(_image, "rm", m.Option("IMAGE_ID"))
}},
}, Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
prefix := []string{cli.SYSTEM, DOCKER, IMAGE}
if len(arg) > 0 {
// 容器详情
res := m.Cmdx(prefix, "inspect", arg[0])
res := m.Cmdx(_image, "inspect", arg[0])
m.Push("detail", kit.KeyValue(map[string]interface{}{}, "", kit.Parse(nil, "", kit.Split(res)...)))
return
}
// 镜像列表
m.Split(strings.Replace(m.Cmdx(prefix, "ls"), "IMAGE ID", "IMAGE_ID", 1), "index", " ", "\n")
m.Split(strings.Replace(m.Cmdx(_image, "ls"), "IMAGE ID", "IMAGE_ID", 1), "index", " ", "\n")
m.Sort("REPOSITORY")
}},
CONTAINER: {Name: "container", Help: "容器管理", List: ListLook("CONTAINER_ID"), Meta: kit.Dict("detail", []string{"进入", "启动", "停止", "重启", "清理", "编辑", "删除"}), Action: map[string]*ice.Action{
"prune": {Name: "prune", Help: "清理", Hand: func(m *ice.Message, arg ...string) {
m.Cmdy(cli.SYSTEM, DOCKER, "prune", "-f")
m.Cmdy(prefix, "prune", "-f")
CONTAINER: {Name: "container CONTAINER_ID=auto auto", Help: "容器管理", Meta: kit.Dict(
"detail", []string{"进入", "启动", "停止", "重启", "清理", "编辑", "删除"},
), Action: map[string]*ice.Action{
gdb.OPEN: {Name: "open", Help: "进入", Hand: func(m *ice.Message, arg ...string) {
m.Cmdy(cli.SYSTEM, "tmux", "new-window", "-t", m.Option("NAMES"), "-n", m.Option("NAMES"),
"-PF", "#{session_name}:#{window_name}.1", "docker exec -it "+m.Option("NAMES")+" bash")
}},
gdb.START: {Name: "start", Help: "启动", Hand: func(m *ice.Message, arg ...string) {
m.Cmdy(_container, "start", m.Option("CONTAINER_ID"))
}},
gdb.STOP: {Name: "stop", Help: "停止", Hand: func(m *ice.Message, arg ...string) {
m.Cmdy(_container, "stop", m.Option("CONTAINER_ID"))
}},
gdb.RESTART: {Name: "restart", Help: "重启", Hand: func(m *ice.Message, arg ...string) {
m.Cmdy(_container, "restart", m.Option("CONTAINER_ID"))
}},
gdb.CHANGE: {Name: "change", Help: "更改", Hand: func(m *ice.Message, arg ...string) {
switch arg[0] {
case "NAMES":
m.Cmdy(_container, "rename", m.Option("CONTAINER_ID"), arg[1])
}
}},
gdb.PRUNE: {Name: "prune", Help: "清理", Hand: func(m *ice.Message, arg ...string) {
m.Cmdy(_container, "prune", "-f")
}},
gdb.CLEAR: {Name: "clear", Help: "删除", Hand: func(m *ice.Message, arg ...string) {
m.Cmdy(_container, "rm", m.Option("CONTAINER_ID"))
}},
}, Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
prefix := []string{cli.SYSTEM, DOCKER, CONTAINER}
if len(arg) > 1 && arg[0] == "action" {
switch arg[1] {
case "进入":
m.Cmdy(cli.SYSTEM, "tmux", "new-window", "-t", m.Option("NAMES"), "-n", m.Option("NAMES"),
"-PF", "#{session_name}:#{window_name}.1", "docker exec -it "+m.Option("NAMES")+" bash").Set("append")
return
case "停止":
m.Cmdy(prefix, "stop", m.Option("CONTAINER_ID"))
case "启动":
m.Cmdy(prefix, "start", m.Option("CONTAINER_ID"))
case "重启":
m.Cmdy(prefix, "restart", m.Option("CONTAINER_ID"))
case "清理":
m.Cmdy(prefix, "prune", "-f")
case "modify":
switch arg[2] {
case "NAMES":
m.Cmdy(prefix, "rename", arg[4], arg[3])
}
case "delete":
m.Cmdy(prefix, "rm", m.Option("CONTAINER_ID")).Set("append")
}
return
}
if len(arg) > 0 {
// 容器详情
res := m.Cmdx(prefix, "inspect", arg[0])
res := m.Cmdx(_container, "inspect", arg[0])
m.Push("detail", kit.KeyValue(map[string]interface{}{}, "", kit.Parse(nil, "", kit.Split(res)...)))
return
}
// 容器列表
m.Split(strings.Replace(m.Cmdx(prefix, "ls", "-a"), "CONTAINER ID", "CONTAINER_ID", 1), "index", " ", "\n")
m.Split(strings.Replace(m.Cmdx(_container, "ls", "-a"), "CONTAINER ID", "CONTAINER_ID", 1), "index", " ", "\n")
m.Sort("NAMES")
m.Table(func(index int, value map[string]string, head []string) {
for _, k := range []string{"open", "start", "stop", "restart", "clear"} {
m.Push(k, m.Cmdx(mdb.RENDER, web.RENDER.Button, k))
}
})
}},
COMMAND: {Name: "command NAMES=auto cmd... auto", Help: "命令管理", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
if len(arg) < 2 {
m.Cmdy(CONTAINER)
return
}
m.Echo(m.Cmdx(_container, "exec", arg[0], kit.Split(kit.Select("pwd", arg, 1), " ", " ")))
}},
"init": {Name: "init", Help: "初始化", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
m.Watch(gdb.DREAM_START, m.Prefix("auto"))
gdb.INIT: {Name: "init", Help: "初始化", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
m.Watch(web.DREAM_START)
return
if m.Richs(web.FAVOR, nil, "alpine.auto", nil) == nil {
m.Cmd(web.FAVOR, "alpine.auto", web.TYPE_SHELL, "镜像源", `sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories`)
@ -102,60 +121,46 @@ var Index = &ice.Context{Name: "docker", Help: "虚拟机",
m.Cmd(web.FAVOR, "alpine.auto", web.TYPE_SHELL, "软件包", `apk add curl`)
}
}},
"auto": {Name: "auto", Help: "自动化", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
prefix := []string{cli.SYSTEM, "docker"}
if m.Cmd(prefix, "container", "start", arg[0]).Append("code") != "1" {
// 启动容器
return
}
args := []string{}
kit.Fetch(m.Confv("docker", "meta.build"), func(index int, value string) {
switch value {
case "home":
args = append(args, "-w", "/root")
case "mount":
args = append(args, "--mount", kit.Format("type=bind,source=%s,target=/root", kit.Path(m.Conf(web.DREAM, "meta.path"), arg[0])))
gdb.AUTO: {Name: "auto", Help: "自动化", Action: map[string]*ice.Action{
web.DREAM_START: {Name: "dream.start", Hand: func(m *ice.Message, arg ...string) {
if m.Cmd(_container, "start", arg[0]).Append(cli.CMD_CODE) == "0" {
// 启动容器
return
}
})
// 创建容器
pid := m.Cmdx(prefix, "run", "-dt", args, "--name", arg[0], "alpine")
m.Log(ice.LOG_CREATE, "%s: %s", arg[0], pid)
args := []string{"--name", arg[0]}
kit.Fetch(m.Confv(DOCKER, "meta.build"), func(index int, value string) {
switch value {
case "home":
args = append(args, "-w", "/root")
case "mount":
p := kit.Path(m.Conf(web.DREAM, "meta.path"), arg[0])
args = append(args, "--mount", kit.Format("type=bind,source=%s,target=/root", p))
m.Cmd(web.FAVOR, kit.Select("alpine.auto", arg, 1)).Table(func(index int, value map[string]string, head []string) {
if value["type"] == web.TYPE_SHELL {
// 执行命令
m.Cmd(prefix, "exec", arg[0], kit.Split(value["text"]))
}
})
}},
p = path.Join(p, ".bashrc")
if _, e := os.Stat(p); e != nil {
m.Cmd(nfs.SAVE, p, kit.Format("export ctx_dev=%s\nexport ctx_pod=%s\n",
m.Conf(cli.RUNTIME, "conf.ctx_dev"), arg[0]))
}
"command": {Name: "command", Help: "命令", List: kit.List(
kit.MDB_INPUT, "text", "name", "CONTAINER_ID",
kit.MDB_INPUT, "text", "name", "cmd", "className", "args cmd",
kit.MDB_INPUT, "button", "value", "执行",
), Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
if len(arg) < 2 {
m.Cmdy("container")
}
})
// 创建容器
repos := m.Conf(DOCKER, "meta.repos")
pid := m.Cmdx(_docker, "run", "-dt", args, repos)
m.Log_CREATE(repos, arg[0], "pid", pid)
return
}
prefix := []string{cli.SYSTEM, "docker", "container"}
m.Cmdy(prefix, "exec", arg[0], arg[1:]).Set("append")
}},
m.Cmd(web.FAVOR, kit.Select(repos+".auto", arg, 1)).Table(func(index int, value map[string]string, head []string) {
if value[kit.MDB_TYPE] == web.TYPE_SHELL {
m.Cmd(_container, "exec", arg[0], kit.Split(value[kit.MDB_TEXT]))
// 执行命令
}
})
}},
}, Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {}},
},
}
func init() { code.Index.Register(Index, nil) }
func ListLook(name ...string) []interface{} {
list := []interface{}{}
for _, k := range name {
list = append(list, kit.MDB_INPUT, "text", "name", k, "action", "auto")
}
return kit.List(append(list,
kit.MDB_INPUT, "button", "name", "查看", "action", "auto",
kit.MDB_INPUT, "button", "name", "返回", "cb", "Last",
)...)
}

View File

@ -4,6 +4,7 @@ import (
ice "github.com/shylinux/icebergs"
"github.com/shylinux/icebergs/base/cli"
"github.com/shylinux/icebergs/base/gdb"
"github.com/shylinux/icebergs/base/mdb"
"github.com/shylinux/icebergs/base/web"
"github.com/shylinux/icebergs/core/code"
kit "github.com/shylinux/toolkits"
@ -14,28 +15,39 @@ import (
"time"
)
const TMUX = "tmux"
const (
TEXT = "text"
BUFFER = "buffer"
SESSION = "session"
WINDOW = "window"
PANE = "pane"
VIEW = "view"
LOCAL = "local"
RELAY = "relay"
)
var _tmux = []string{cli.SYSTEM, TMUX}
var Index = &ice.Context{Name: "tmux", Help: "工作台",
Caches: map[string]*ice.Cache{},
Configs: map[string]*ice.Config{
"prefix": {Name: "prefix", Help: "前缀", Value: kit.Data("cmd", []interface{}{cli.SYSTEM, "tmux"})},
"buffer": {Name: "buffer", Help: "缓存", Value: kit.Data()},
"session": {Name: "session", Help: "会话", Value: kit.Data(
SESSION: {Name: "session", Help: "会话", Value: kit.Data(
"format", "#{session_id},#{session_attached},#{session_name},#{session_windows},#{session_height},#{session_width}",
"fields", "id,tag,session,windows,height,width",
)},
"windows": {Name: "window", Help: "窗口", Value: kit.Data(
WINDOW: {Name: "windows", Help: "窗口", Value: kit.Data(
"format", "#{window_id},#{window_active},#{window_name},#{window_panes},#{window_height},#{window_width}",
"fields", "id,tag,window,panes,height,width",
)},
"panes": {Name: "pane", Help: "终端", Value: kit.Data(
PANE: {Name: "panes", Help: "终端", Value: kit.Data(
"format", "#{pane_id},#{pane_active},#{pane_index},#{pane_tty},#{pane_height},#{pane_width}",
"fields", "id,tag,pane,tty,height,width",
)},
"view": {Name: "pane", Help: "终端", Value: kit.Data()},
"local": {Name: "local", Help: "虚拟机", Value: kit.Data(kit.MDB_SHORT, kit.MDB_NAME)},
"relay": {Name: "relay", Help: "跳板机", Value: kit.Data(kit.MDB_SHORT, kit.MDB_NAME,
LOCAL: {Name: "local", Help: "虚拟机", Value: kit.Data(kit.MDB_SHORT, kit.MDB_NAME)},
RELAY: {Name: "relay", Help: "跳板机", Value: kit.Data(kit.MDB_SHORT, kit.MDB_NAME,
"count", 100, "sleep", "100ms", "tail", kit.Dict(
"verify", "Verification code:",
"password", "Password:",
@ -44,6 +56,151 @@ var Index = &ice.Context{Name: "tmux", Help: "工作台",
)},
},
Commands: map[string]*ice.Command{
TEXT: {Name: "text 保存:button text:textarea", Help: "文本", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
if len(arg) > 0 && arg[0] != "" {
m.Cmd(_tmux, "set-buffer", arg[0])
}
m.Echo(m.Cmdx(_tmux, "show-buffer"))
}},
BUFFER: {Name: "buffer [buffer=auto [value]] auto", Help: "缓存", Action: map[string]*ice.Action{
mdb.MODIFY: {Name: "modify", Help: "编辑", Hand: func(m *ice.Message, arg ...string) {
switch arg[0] {
case "text":
m.Cmd(_tmux, "set-buffer", "-b", m.Option("buffer"), arg[1])
}
}},
}, Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
if len(arg) > 1 {
// 设置缓存
m.Cmd(_tmux, "set-buffer", "-b", arg[0], arg[1])
}
if len(arg) > 0 {
// 查看缓存
m.Echo(m.Cmdx(_tmux, "show-buffer", "-b", arg[0]))
return
}
// 缓存列表
for i, v := range kit.Split(m.Cmdx(_tmux, "list-buffers"), "\n", "\n", "\n") {
ls := strings.SplitN(v, ": ", 3)
m.Push("buffer", ls[0])
m.Push("size", ls[1])
if i < 3 {
m.Push("text", m.Cmdx(_tmux, "show-buffer", "-b", ls[0]))
} else {
m.Push("text", ls[2][1:])
}
}
}},
SESSION: {Name: "session [session=auto [window=auto [pane=auto [cmd]]]] auto", Help: "会话管理", Meta: kit.Dict(
"detail", []string{"选择", "编辑", "删除"},
), Action: map[string]*ice.Action{
"choice": {Name: "choice", Help: "选择", Hand: func(m *ice.Message, arg ...string) {
m.Cmd(_tmux, "switch-client", "-t", m.Option(SESSION))
if m.Option(WINDOW) != "" {
m.Cmd(_tmux, "select-window", "-t", m.Option(SESSION)+":"+m.Option(WINDOW))
}
if m.Option(PANE) != "" {
m.Cmd(_tmux, "select-pane", "-t", m.Option(SESSION)+":"+m.Option(WINDOW)+"."+m.Option(PANE))
}
}},
mdb.MODIFY: {Name: "modify", Help: "编辑", Hand: func(m *ice.Message, arg ...string) {
switch arg[0] {
case SESSION:
// 重命名会话
m.Cmd(_tmux, "rename-session", "-t", m.Option(SESSION), arg[1])
case WINDOW:
// 重命名窗口
m.Cmd(_tmux, "rename-window", "-t", m.Option(SESSION)+":"+m.Option(WINDOW), arg[1])
}
}},
gdb.CLEAR: {Name: "clear", Help: "删除", Hand: func(m *ice.Message, arg ...string) {
if m.Option(PANE) != "" {
m.Cmd(_tmux, "kill-pane", "-t", m.Option(SESSION)+":"+m.Option(WINDOW)+"."+m.Option(PANE))
return
}
if m.Option(WINDOW) != "" {
m.Cmd(_tmux, "kill-window", "-t", m.Option(SESSION)+":"+m.Option(WINDOW))
return
}
if m.Option(SESSION) != "" {
m.Cmd(_tmux, "kill-session", "-t", m.Option(SESSION))
return
}
}},
}, Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
target := ""
if len(arg) > 3 {
// 执行命令
target = arg[0] + ":" + arg[1] + "." + arg[2]
m.Cmd(_tmux, "send-keys", "-t", target, strings.Join(arg[3:], " "), "Enter")
time.Sleep(1 * time.Second)
}
if len(arg) > 2 {
// 终端内容
m.Echo(strings.TrimSpace(m.Cmdx(VIEW, target)))
return
}
if len(arg) == 0 {
// 会话列表
m.Split(m.Cmdx(_tmux, "list-session", "-F", m.Conf(cmd, "meta.format")), m.Conf(cmd, "meta.fields"), ",", "\n")
m.Table(func(index int, value map[string]string, head []string) {
for _, k := range []string{"clear"} {
m.Push(k, m.Cmdx(mdb.RENDER, web.RENDER.Button, k))
}
})
return
}
target = arg[0]
if m.Cmd(_tmux, "has-session", "-t", target).Append(cli.CMD_CODE) != "0" {
// 创建会话
m.Option(cli.CMD_ENV, "TMUX", "")
m.Option(cli.CMD_DIR, m.Conf(web.DREAM, "meta.path"))
m.Cmd(_tmux, "new-session", "-ds", arg[0])
// m.Cmd("auto", arg[0])
}
if len(arg) == 1 {
// 窗口列表
m.Cmdy(WINDOW, target)
return
}
switch arg[1] {
case "has":
m.Cmd(WINDOW, target).Table(func(index int, value map[string]string, head []string) {
if value["window"] == arg[2] {
m.Echo("true")
}
})
return
}
if target = arg[0] + ":" + arg[1]; m.Cmd(_tmux, "rename-window", "-t", target, arg[1]).Append(cli.CMD_CODE) != "0" {
// 创建窗口
m.Cmd(_tmux, "switch-client", "-t", arg[0])
m.Cmd(_tmux, "new-window", "-t", arg[0], "-dn", arg[1])
}
if len(arg) == 2 {
// 终端列表
m.Cmdy(PANE, target)
return
}
}},
WINDOW: {Name: "windows", Help: "窗口", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
m.Split(m.Cmdx(_tmux, "list-windows", "-t", kit.Select("", arg, 0),
"-F", m.Conf(cmd, "meta.format")), m.Conf(cmd, "meta.fields"), ",", "\n")
}},
PANE: {Name: "panes", Help: "终端", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
m.Split(m.Cmdx(_tmux, "list-panes", "-t", kit.Select("", arg, 0),
"-F", m.Conf(cmd, "meta.format")), m.Conf(cmd, "meta.fields"), ",", "\n")
}},
VIEW: {Name: "view", Help: "终端", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
m.Cmdy(_tmux, "capture-pane", "-pt", kit.Select("", arg, 0)).Set(ice.MSG_APPEND)
}},
ice.CTX_INIT: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
if m.Cmdy(cli.SYSTEM, "tmux", "ls"); m.Append("code") != "0" {
return
@ -67,8 +224,9 @@ var Index = &ice.Context{Name: "tmux", Help: "工作台",
code.PROJECT: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
}},
"init": {Name: "init", Help: "初始化", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
m.Watch(gdb.DREAM_START, m.Prefix("auto"))
gdb.INIT: {Name: "init", Help: "初始化", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
m.Watch(gdb.DREAM_START)
return
if m.Richs(web.FAVOR, nil, "tmux.auto", nil) == nil {
m.Cmd(web.FAVOR, "tmux.auto", web.TYPE_SHELL, "脚本", `curl $ctx_dev/publish/auto.sh > auto.sh`)
@ -86,64 +244,73 @@ var Index = &ice.Context{Name: "tmux", Help: "工作台",
}
}
}},
"auto": {Name: "auto dream", Help: "自动化", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
prefix := kit.Simple(m.Confv("prefix", "meta.cmd"))
// 共享空间
share, dev := "", kit.Select(m.Conf(cli.RUNTIME, "conf.ctx_dev"), m.Conf(cli.RUNTIME, "host.ctx_self"))
m.Richs(web.SPACE, nil, arg[0], func(key string, value map[string]interface{}) {
share = kit.Format(value["share"])
})
// 环境变量
m.Option("cmd_env", "TMUX", "", "ctx_dev", dev, "ctx_share", share)
m.Option("cmd_dir", path.Join(m.Conf(web.DREAM, "meta.path"), arg[0]))
if arg[0] != "" && m.Cmd(prefix, "has-session", "-t", arg[0]).Append("code") != "0" {
// 创建会话
m.Cmd(prefix, "new-session", "-ds", arg[0])
}
if m.Option("local") != "" {
// 创建容器
m.Cmd("local", m.Option("local"), arg[0])
}
if m.Option("relay") != "" {
// 远程登录
m.Cmd("relay", m.Option("relay"), arg[0])
}
for _, v := range kit.Simple(m.Optionv("before")) {
// 前置命令
m.Cmdy(prefix, "send-keys", "-t", arg[0], v, "Enter")
}
// 连接参数
m.Cmdy(prefix, "send-keys", "-t", arg[0], "export ctx_dev=", dev, "Enter")
m.Cmdy(prefix, "send-keys", "-t", arg[0], "export ctx_share=", share, "Enter")
m.Cmd(web.FAVOR, kit.Select("tmux.auto", arg, 1)).Table(func(index int, value map[string]string, head []string) {
switch value["type"] {
case web.TYPE_SHELL:
// 发送命令
m.Cmdy(prefix, "send-keys", "-t", arg[0], value["text"], "Enter")
time.Sleep(10 * time.Millisecond)
gdb.AUTO: {Name: "auto", Help: "自动化", Action: map[string]*ice.Action{
web.DREAM_START: {Name: "dream.start", Hand: func(m *ice.Message, arg ...string) {
if m.Cmd(_tmux, "has-session", "-t", arg[0]).Append(cli.CMD_CODE) == "0" {
return
}
})
// 创建会话
m.Option(cli.CMD_ENV, "TMUX", "", "ctx_pod", arg[0], "ctx_dev", m.Conf(cli.RUNTIME, "conf.ctx_dev"))
m.Option(cli.CMD_DIR, path.Join(m.Conf(web.DREAM, "meta.path"), arg[0]))
m.Cmd(_tmux, "new-session", "-ds", arg[0])
return
// 共享空间
share, dev := "", kit.Select(m.Conf(cli.RUNTIME, "conf.ctx_dev"), m.Conf(cli.RUNTIME, "host.ctx_self"))
m.Richs(web.SPACE, nil, arg[0], func(key string, value map[string]interface{}) {
share = kit.Format(value["share"])
})
// 环境变量
m.Option("cmd_env", "TMUX", "", "ctx_dev", dev, "ctx_share", share)
m.Option("cmd_dir", path.Join(m.Conf(web.DREAM, "meta.path"), arg[0]))
if arg[0] != "" && m.Cmd(_tmux, "has-session", "-t", arg[0]).Append("code") != "0" {
// 创建会话
m.Cmd(_tmux, "new-session", "-ds", arg[0])
}
if m.Option("local") != "" {
// 创建容器
m.Cmd("local", m.Option("local"), arg[0])
}
if m.Option("relay") != "" {
// 远程登录
m.Cmd("relay", m.Option("relay"), arg[0])
}
for _, v := range kit.Simple(m.Optionv("before")) {
// 前置命令
m.Cmdy(_tmux, "send-keys", "-t", arg[0], v, "Enter")
}
// 连接参数
m.Cmdy(_tmux, "send-keys", "-t", arg[0], "export ctx_dev=", dev, "Enter")
m.Cmdy(_tmux, "send-keys", "-t", arg[0], "export ctx_share=", share, "Enter")
m.Cmd(web.FAVOR, kit.Select("tmux.auto", arg, 1)).Table(func(index int, value map[string]string, head []string) {
switch value["type"] {
case web.TYPE_SHELL:
// 发送命令
m.Cmdy(_tmux, "send-keys", "-t", arg[0], value["text"], "Enter")
time.Sleep(10 * time.Millisecond)
}
})
for _, v := range kit.Simple(m.Optionv("after")) {
// 后置命令
m.Cmdy(_tmux, "send-keys", "-t", arg[0], v, "Enter")
}
}},
}, Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {}},
for _, v := range kit.Simple(m.Optionv("after")) {
// 后置命令
m.Cmdy(prefix, "send-keys", "-t", arg[0], v, "Enter")
}
}},
"make": {Name: "make name cmd...", Help: "个性化", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
prefix := kit.Simple(m.Confv("prefix", "meta.cmd"))
session := m.Conf(cli.RUNTIME, "node.name")
if arg[1] == "session" {
session, arg[2], arg = arg[2], arg[0], arg[2:]
}
if m.Warn(m.Cmd(prefix, "has-session", "-t", session).Append("code") != "0", "session miss") {
if m.Warn(m.Cmd(_tmux, "has-session", "-t", session).Append("code") != "0", "session miss") {
// 会话不存在
return
}
@ -155,183 +322,34 @@ var Index = &ice.Context{Name: "tmux", Help: "工作台",
switch arg[1] {
case "init":
m.Cmdx(prefix, "rename-window", "-t", session, arg[0])
m.Cmdx(_tmux, "rename-window", "-t", session, arg[0])
arg[1], arg = arg[0], arg[1:]
case "link":
m.Cmdx(prefix, "link-window", "-dt", session, "-s", arg[2])
m.Cmdx(_tmux, "link-window", "-dt", session, "-s", arg[2])
return
default:
m.Cmd(prefix, "new-window", "-dt", session, "-n", arg[0])
m.Cmd(_tmux, "new-window", "-dt", session, "-n", arg[0])
}
for _, v := range arg[1:] {
switch ls := kit.Split(v); ls[1] {
case "v":
m.Cmd(prefix, "split-window", "-h", "-dt", session+":"+arg[0]+"."+ls[0], ls[2:])
m.Cmd(_tmux, "split-window", "-h", "-dt", session+":"+arg[0]+"."+ls[0], ls[2:])
case "u", "split-window":
m.Cmd(prefix, "split-window", "-dt", session+":"+arg[0]+"."+ls[0], ls[2:])
m.Cmd(_tmux, "split-window", "-dt", session+":"+arg[0]+"."+ls[0], ls[2:])
case "k":
m.Cmd(prefix, "send-key", "-t", session+":"+arg[0]+"."+ls[0], ls[2:])
m.Cmd(_tmux, "send-key", "-t", session+":"+arg[0]+"."+ls[0], ls[2:])
default:
m.Cmd(prefix, ls[1], "-t", session+":"+arg[0]+"."+ls[0], ls[2:])
m.Cmd(_tmux, ls[1], "-t", session+":"+arg[0]+"."+ls[0], ls[2:])
}
}
}},
"text": {Name: "text name 保存:button text:textarea", Help: "文本", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
prefix := kit.Simple(m.Confv("prefix", "meta.cmd"))
if len(arg) > 1 && arg[1] != "" {
m.Cmd(prefix, "set-buffer", arg[1])
}
m.Cmdy(prefix, "show-buffer").Set(ice.MSG_APPEND)
}},
"buffer": {Name: "buffer [buffer=auto [value]] auto", Help: "缓存", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
prefix := kit.Simple(m.Confv("prefix", "meta.cmd"))
if len(arg) > 1 {
// 设置缓存
m.Cmd(prefix, "set-buffer", "-b", arg[0], arg[1])
}
if len(arg) > 0 {
// 查看缓存
m.Cmdy(prefix, "show-buffer", "-b", arg[0]).Set(ice.MSG_APPEND)
return
}
// 缓存列表
for i, v := range kit.Split(m.Cmdx(prefix, "list-buffers"), "\n", "\n", "\n") {
ls := strings.SplitN(v, ": ", 3)
m.Push("buffer", ls[0])
m.Push("size", ls[1])
if i < 3 {
m.Push("text", m.Cmdx(prefix, "show-buffer", "-b", ls[0]))
} else {
m.Push("text", ls[2][1:])
}
}
}},
"session": {Name: "session [session=auto [window=auto [pane=auto [cmd]]]] auto", Help: "会话", Meta: kit.Dict(
"detail", []string{"选择", "编辑", "删除", "下载"},
), Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
prefix := kit.Simple(m.Confv("prefix", "meta.cmd"))
if len(arg) > 1 && arg[0] == "action" {
switch arg[1] {
case "select", "选择":
if arg[2] == "session" {
// 选择会话
m.Cmd(prefix, "switch-client", "-t", arg[3])
break
}
if m.Cmd(prefix, "switch-client", "-t", m.Option("session")); arg[2] == "window" {
// 选择窗口
m.Cmd(prefix, "select-window", "-t", m.Option("session")+":"+arg[3])
break
}
if m.Cmd(prefix, "select-window", "-t", m.Option("session")+":"+m.Option("window")); arg[2] == "pane" {
// 选择终端
m.Cmd(prefix, "select-pane", "-t", m.Option("session")+":"+m.Option("window")+"."+arg[3])
}
case "modify", "编辑":
switch arg[2] {
case "session":
// 重命名会话
m.Cmd(prefix, "rename-session", "-t", arg[4], arg[3])
case "window":
// 重命名窗口
m.Cmd(prefix, "rename-window", "-t", m.Option("session")+":"+arg[4], arg[3])
}
case "delete", "删除":
switch arg[2] {
case "session":
// 删除会话
m.Cmd(prefix, "kill-session", "-t", arg[3])
case "window":
// 删除窗口
m.Cmd(prefix, "kill-window", "-t", m.Option("session")+":"+arg[3])
case "pane":
// 删除终端
m.Cmd(prefix, "kill-pane", "-t", m.Option("session")+":"+m.Option("window")+"."+arg[3])
}
}
return
}
if len(arg) == 0 {
// 会话列表
m.Split(m.Cmdx(prefix, "list-session", "-F", m.Conf(cmd, "meta.format")), m.Conf(cmd, "meta.fields"), ",", "\n")
return
}
target := arg[0]
if m.Cmd(prefix, "has-session", "-t", target).Append("code") != "0" {
// 创建会话
m.Option("cmd_env", "TMUX", "")
m.Option("cmd_dir", m.Conf(web.DREAM, "meta.path"))
m.Cmd(prefix, "new-session", "-ds", arg[0])
m.Cmd("auto", arg[0])
}
if len(arg) == 1 {
// 窗口列表
m.Cmdy("windows", target)
return
}
switch arg[1] {
case "has":
m.Cmd("windows", target).Table(func(index int, value map[string]string, head []string) {
if value["window"] == arg[2] {
m.Echo("true")
}
})
return
}
if target = arg[0] + ":" + arg[1]; m.Cmd(prefix, "rename-window", "-t", target, arg[1]).Append("code") != "0" {
// 创建窗口
m.Cmd(prefix, "switch-client", "-t", arg[0])
m.Cmd(prefix, "new-window", "-t", arg[0], "-dn", arg[1])
}
if len(arg) == 2 {
// 终端列表
m.Cmdy("panes", target)
return
}
if target = arg[0] + ":" + arg[1] + "." + arg[2]; len(arg) > 3 {
// 执行命令
m.Cmd(prefix, "send-keys", "-t", target, strings.Join(arg[3:], " "), "Enter")
time.Sleep(1 * time.Second)
}
// 终端内容
m.Echo(strings.TrimSpace(m.Cmdx("view", target)))
}},
"windows": {Name: "window", Help: "窗口", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
prefix := kit.Simple(m.Confv("prefix", "meta.cmd"))
m.Split(m.Cmdx(prefix, "list-windows", "-t", kit.Select("", arg, 0),
"-F", m.Conf(cmd, "meta.format")), m.Conf(cmd, "meta.fields"), ",", "\n")
}},
"panes": {Name: "pane", Help: "终端", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
prefix := kit.Simple(m.Confv("prefix", "meta.cmd"))
m.Split(m.Cmdx(prefix, "list-panes", "-t", kit.Select("", arg, 0),
"-F", m.Conf(cmd, "meta.format")), m.Conf(cmd, "meta.fields"), ",", "\n")
}},
"view": {Name: "view", Help: "终端", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
prefix := kit.Simple(m.Confv("prefix", "meta.cmd"))
m.Cmdy(prefix, "capture-pane", "-pt", kit.Select("", arg, 0)).Set(ice.MSG_APPEND)
}},
"local": {Name: "local name name", Help: "虚拟机", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
prefix := kit.Simple(m.Confv("prefix", "meta.cmd"))
m.Cmd("web.code.docker.auto", arg[1])
m.Cmdy(prefix, "send-keys", "-t", arg[1], "docker exec -it ", arg[1], " bash", "Enter")
m.Cmdy(_tmux, "send-keys", "-t", arg[1], "docker exec -it ", arg[1], " bash", "Enter")
}},
"relay": {Name: "relay [name [favor]]", Help: "跳板机", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
prefix := kit.Simple(m.Confv("prefix", "meta.cmd"))
if len(arg) == 0 {
// 认证列表
m.Richs(cmd, nil, "*", func(key string, value map[string]interface{}) {
@ -357,22 +375,22 @@ var Index = &ice.Context{Name: "tmux", Help: "工作台",
m.Richs(cmd, nil, arg[0], func(key string, value map[string]interface{}) {
// 登录命令
m.Cmdy(prefix, "send-keys", "-t", arg[1], kit.Format("ssh %s@%s", value["username"], value["website"]), "Enter")
m.Cmdy(_tmux, "send-keys", "-t", arg[1], kit.Format("ssh %s@%s", value["username"], value["website"]), "Enter")
sleep := kit.Duration(m.Conf(cmd, "meta.sleep"))
for i := 0; i < kit.Int(m.Conf(cmd, "meta.count")); i++ {
time.Sleep(sleep)
list := strings.Split(strings.TrimSpace(m.Cmdx(prefix, "capture-pane", "-p")), "\n")
list := strings.Split(strings.TrimSpace(m.Cmdx(_tmux, "capture-pane", "-p")), "\n")
if tail := list[len(list)-1]; tail == m.Conf(cmd, "meta.tail.login") {
// 登录成功
break
} else if tail == m.Conf(cmd, "meta.tail.password") {
// 输入密码
m.Cmdy(prefix, "send-keys", "-t", arg[1], value["password"], "Enter")
m.Cmdy(_tmux, "send-keys", "-t", arg[1], value["password"], "Enter")
} else if tail == m.Conf(cmd, "meta.tail.verify") {
// 输入密码
m.Cmdy(prefix, "send-keys", "-t", arg[1], m.Cmdx("aaa.totp.get", value["text"]), "Enter")
m.Cmdy(_tmux, "send-keys", "-t", arg[1], m.Cmdx("aaa.totp.get", value["text"]), "Enter")
}
}
})

View File

@ -562,7 +562,7 @@ func (m *Message) Cmd(arg ...interface{}) *Message {
})
})
if m.Warn(m.Hand == false, "not found %v", list) {
if m.Warn(m.Hand == false, ErrNotFound, list) {
return m.Set(MSG_RESULT).Cmd("cli.system", list)
}
return m