From a95dd9a346f1de567a2c495177da4a021f84f65d Mon Sep 17 00:00:00 2001 From: shaoying Date: Fri, 11 Jan 2019 21:41:20 +0800 Subject: [PATCH] opt nfs --- etc/exit.shy | 8 -- etc/init.shy | 17 +-- src/contexts/cli/cli.go | 128 +++++++------------- src/contexts/ctx/ctx.go | 38 +++--- src/contexts/gdb/gdb.go | 4 + src/contexts/log/log.go | 80 ++++++++----- src/contexts/nfs/nfs.go | 251 ++++++++++++++++++---------------------- src/contexts/ssh/ssh.go | 53 ++++++--- src/contexts/tcp/tcp.go | 6 +- src/contexts/yac/yac.go | 21 +++- src/toolkit/kit.go | 30 ++--- 11 files changed, 312 insertions(+), 324 deletions(-) diff --git a/etc/exit.shy b/etc/exit.shy index 6a818b89..e69de29b 100644 --- a/etc/exit.shy +++ b/etc/exit.shy @@ -1,8 +0,0 @@ - -~web - config save web.json bench -~aaa - config save auth.json hash auth -~stdio - config save history.json history - diff --git a/etc/init.shy b/etc/init.shy index 947cfe66..c3a948b4 100644 --- a/etc/init.shy +++ b/etc/init.shy @@ -1,15 +1,2 @@ -~stdio -config load history.json -~aaa - # config load auth.json -~web -config load web.json - -~aaa - role root componet index command source - user root shy shy - -source etc/local.shy -source etc/spide.shy -~aaa - +~ssh + remote listen :9090 diff --git a/src/contexts/cli/cli.go b/src/contexts/cli/cli.go index 0f003ede..44f59486 100644 --- a/src/contexts/cli/cli.go +++ b/src/contexts/cli/cli.go @@ -58,7 +58,7 @@ func (cli *CLI) Begin(m *ctx.Message, arg ...string) ctx.Server { return cli } func (cli *CLI) Start(m *ctx.Message, arg ...string) bool { - m.Cap("stream", m.Spawn(m.Sess("yac", false).Target()).Call(func(cmd *ctx.Message) *ctx.Message { + m.Cap("stream", m.Sess("yac").Call(func(cmd *ctx.Message) *ctx.Message { if !m.Caps("parse") { switch cmd.Detail(0) { case "if": @@ -81,9 +81,6 @@ func (cli *CLI) Start(m *ctx.Message, arg ...string) bool { if v != nil { m.Optionv("ps_target", v) } - - m.Set("append").Copy(cmd, "append") - m.Set("result").Copy(cmd, "result") return nil }, "scan", arg).Target().Name) @@ -136,6 +133,45 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心", "timer_next": &ctx.Config{Name: "timer_next", Value: "", Help: "定时器"}, }, Commands: map[string]*ctx.Command{ + "source": &ctx.Command{Name: "source [script|stdio|snippet]", Help: "解析脚本, script: 脚本文件, stdio: 命令终端, snippet: 代码片段", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { + if len(arg) == 0 { + m.Cmdy("dir", "dir_deep", "dir_reg", ".*\\.(sh|shy|py)$") + return + } + + // 解析脚本文件 + if m.Cmds("nfs.path", arg[0]) { + switch path.Ext(arg[0]) { + case "": + case ".shy": + m.Option("scan_end", "false") + m.Start(fmt.Sprintf("shell%d", m.Capi("nshell", 1)), "shell", arg...) + m.Wait() + default: + m.Cmdy("system", m.Conf("cmd_script", strings.TrimPrefix(path.Ext(arg[0]), ".")), arg) + } + return + } + + // 解析终端命令 + if arg[0] == "stdio" { + m.Option("scan_end", "false") + m.Start("shy", "shell", "stdio", "engine") + m.Wait() + return + } + + // 解析代码片段 + m.Sess("yac").Call(func(msg *ctx.Message) *ctx.Message { + switch msg.Cmd().Detail(0) { + case "cmd": + m.Set("append").Copy(msg, "append") + m.Set("result").Copy(msg, "result") + } + return nil + }, "parse", "line", "void", strings.Join(arg, " ")) + return + }}, "system": &ctx.Command{Name: "system word...", Help: []string{"调用系统命令, word: 命令", "cmd_active(true/false): 是否交互", "cmd_timeout: 命令超时", "cmd_env: 环境变量", "cmd_dir: 工作目录"}, Form: map[string]int{"cmd_active": 1, "cmd_timeout": 1, "cmd_env": 2, "cmd_dir": 1, "cmd_error": 0, "cmd_parse": 1}, @@ -163,9 +199,7 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心", if v, ok := kit.Chain(conf, "path").(string); ok { cmd.Path = m.Parse(v) } - m.Log("info", "cmd.path %v", cmd.Path) - - m.Log("info", "cmd.arg %v", cmd.Args) + m.Log("info", "cmd %v %v", cmd.Path, cmd.Args) for k, v := range m.Confm("system_env") { cmd.Env = append(cmd.Env, fmt.Sprintf("%s=%s", k, m.Parse(v))) @@ -200,11 +234,10 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心", } else { wait := make(chan bool, 1) go func() { - out := bytes.NewBuffer(make([]byte, 1024)) - err := bytes.NewBuffer(make([]byte, 1024)) + out := bytes.NewBuffer(make([]byte, 0, 1024)) + err := bytes.NewBuffer(make([]byte, 0, 1024)) cmd.Stdout = out cmd.Stderr = err - if e := cmd.Run(); e != nil { m.Echo("error: ").Echo("%s\n", e).Echo(err.String()) } else { @@ -254,6 +287,7 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心", } return }}, + "alias": &ctx.Command{Name: "alias [short [long...]]|[delete short]|[import module [command [alias]]]", Help: "查看、定义或删除命令别名, short: 命令别名, long: 命令原名, delete: 删除别名, import导入模块所有命令", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { @@ -683,80 +717,6 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心", m.Set("result", m.Optionv("arguments")) return }}, - "source": &ctx.Command{Name: "source [stdio [init_shy [exit_shy]]]|[filename [async]]|string", Help: "解析脚本, filename: 文件名, async: 异步执行", - Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { - if _, ok := m.Source().Server.(*CLI); ok { - m.Copy(m.Spawn(c), "target") - } - - if (len(arg) == 0 || arg[0] == "stdio") && m.Target().Name == "cli" { - // 启动终端 - m.Cmd("yac.init") - m.Optionv("ps_target", m.Target()) - if m.Start("shy", "shell", "stdio"); m.Cmds("nfs.path", m.Confx("init_shy", arg, 1)) { - // msg := m.Spawn().Add("option", "scan_end", "false").Cmd("source", m.Conf("init_shy")) - - // m.Cap("ps_target", msg.Append("last_target")) - // m.Option("prompt", m.Conf("prompt")) - // m.Find("nfs.stdio").Cmd("prompt") - } - if m.Wait(); m.Cmds("nfs.path", m.Confx("exit_shy", arg, 2)) { - m.Spawn().Add("option", "scan_end", "false").Cmd("source", m.Conf("exit_shy")) - } - return - } - - // 运行脚本 - if m.Cmds("nfs.path", arg[0]) && strings.HasSuffix(arg[0], ".shy") { - m.Start(fmt.Sprintf("shell%d", m.Capi("nshell", 1)), "shell", arg...) - if len(arg) < 2 || arg[1] != "async" { - m.Wait() - } else { - m.Options("async", true) - } - return - } - - // m.Confv("source_list", -1, map[string]interface{}{ - // "source_time": m.Time(), - // "source_ctx": m.Option("current_ctx"), - // "source_cmd": strings.Join(arg, " "), - // }) - // - if m.Options("current_ctx") { - args := []string{"context", m.Option("current_ctx")} - arg = append(args, arg...) - m.Option("current_ctx", "") - } else { - if !strings.HasPrefix(arg[0], "context") { - args := []string{"context", m.Source().Name} - arg = append(args, arg...) - } - } - - m.Sess("yac").Call(func(msg *ctx.Message) *ctx.Message { - switch msg.Cmd().Detail(0) { - case "cmd": - m.Set("append").Copy(msg, "append") - m.Set("result").Copy(msg, "result") - } - return nil - }, "parse", "line", "void", strings.Join(arg, " ")) - return - }}, - "run": &ctx.Command{Name: "run", Help: "脚本参数", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { - if len(arg) == 0 { - name := path.Join(m.Option("dir_root"), m.Option("download_dir")) - msg := m.Sess("nfs").Add("option", "dir_reg", ".*\\.(sh|shy|py)$").Add("option", "dir_root", "").Cmd("dir", name, "dir_deep") - m.Copy(msg, "append").Copy(msg, "result") - return - } - - // name := path.Join(m.Option("dir_root"), m.Option("download_dir"), arg[0]) - msg := m.Spawn(c).Cmd("cmd", arg[0], arg[1:]) - m.Copy(msg, "append").Copy(msg, "result") - return - }}, "tmux": &ctx.Command{Name: "tmux buffer", Help: "终端管理, buffer: 查看复制", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { switch arg[0] { diff --git a/src/contexts/ctx/ctx.go b/src/contexts/ctx/ctx.go index e5992536..982139d3 100644 --- a/src/contexts/ctx/ctx.go +++ b/src/contexts/ctx/ctx.go @@ -105,6 +105,7 @@ func (c *Context) Begin(m *Message, arg ...string) *Context { c.message = m c.requests = append(c.requests, m) m.source.sessions = append(m.source.sessions, m) + c.exit = make(chan bool, 3) switch v := m.Gdb("context", "begin", c.Name).(type) { case string: @@ -147,7 +148,6 @@ func (c *Context) Start(m *Message, arg ...string) bool { return true } - c.exit = make(chan bool, 2) go m.TryCatch(m, true, func(m *Message) { m.Log(m.Cap("status", "start"), "%d server %v %v", m.Capi("nserver", 1), m.Meta["detail"], m.Meta["option"]) @@ -170,10 +170,10 @@ func (c *Context) Close(m *Message, arg ...string) bool { return true } - m.Log("close", "before %d:%d %v", len(c.requests), len(c.sessions), arg) if m.target == c { for i := len(c.requests) - 1; i >= 0; i-- { if msg := c.requests[i]; msg.code == m.code { + m.Log("close", "request %d/%d", i, len(c.requests)-1) if c.Server == nil || c.Server.Close(m, arg...) { for j := i; j < len(c.requests)-1; j++ { c.requests[j] = c.requests[j+1] @@ -184,7 +184,6 @@ func (c *Context) Close(m *Message, arg ...string) bool { } } - m.Log("close", "after %d:%d %v", len(c.requests), len(c.sessions), arg) if len(c.requests) > 0 { return false } @@ -200,9 +199,7 @@ func (c *Context) Close(m *Message, arg ...string) bool { if c.context != nil { m.Log("close", "%d context %v", m.root.Capi("ncontext", -1), arg) - if c.Name != "stdio" { - delete(c.context.contexts, c.Name) - } + delete(c.context.contexts, c.Name) c.exit <- true } return true @@ -1112,6 +1109,7 @@ func (m *Message) Sess(key string, arg ...interface{}) *Message { if x, ok := msg.Sessions[key]; ok { if spawn { x = m.Spawn(x.target) + x.callback = func(sub *Message) *Message { return sub } } return x } @@ -1292,6 +1290,9 @@ func (m *Message) Cmd(args ...interface{}) *Message { arg = args } + target := m.target + m.target = s + m.Hand = true switch v := m.Gdb("command", key, arg).(type) { case string: @@ -1299,6 +1300,9 @@ func (m *Message) Cmd(args ...interface{}) *Message { case nil: x.Hand(m, c, key, arg...) } + if m.target == s { + m.target = target + } }) } return m.Hand @@ -3266,11 +3270,18 @@ func (ctx *CTX) Begin(m *Message, arg ...string) Server { return ctx } func (ctx *CTX) Start(m *Message, arg ...string) bool { - gdb := m.Sess("gdb") - gdb.Target().Start(gdb) + m.Optionv("ps_target", Index) + + m.Cmd("log.init") + m.Cmd("gdb.init") + if m.Cmd("yac.init", "lex"); len(arg) == 0 { + m.Cap("stream", "shy") + m.Cmd("cli.source", "init.shy").Cmd("cli.source", "stdio").Cmd("cli.source", "exit.shy") + return true + } m.Cmd("cli.source", arg) - return false + return true } func (ctx *CTX) Close(m *Message, arg ...string) bool { return true @@ -3283,8 +3294,9 @@ func Start(args ...string) bool { args = append(args, os.Args[1:]...) } - Index.Begin(Pulse, args...) - Index.Start(Pulse, args...) - Index.Close(Pulse, args...) - return false + if Index.Begin(Pulse, args...); Index.Start(Pulse, args...) { + return Index.Close(Pulse, args...) + } + + return Index.message.Wait() } diff --git a/src/contexts/gdb/gdb.go b/src/contexts/gdb/gdb.go index d32618cd..be33cb0c 100644 --- a/src/contexts/gdb/gdb.go +++ b/src/contexts/gdb/gdb.go @@ -121,6 +121,10 @@ var Index = &ctx.Context{Name: "gdb", Help: "调试中心", }}, }, Commands: map[string]*ctx.Command{ + "init": &ctx.Command{Name: "init", Help: "等待调试", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { + m.Target().Start(m) + return + }}, "demo": &ctx.Command{Name: "wait arg...", Help: "等待调试", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { m.Echo("hello world") return diff --git a/src/contexts/log/log.go b/src/contexts/log/log.go index b0af0a17..061eb633 100644 --- a/src/contexts/log/log.go +++ b/src/contexts/log/log.go @@ -11,7 +11,8 @@ import ( ) type LOG struct { - file map[string]*os.File + queue chan map[string]interface{} + file map[string]*os.File *ctx.Context } @@ -33,29 +34,12 @@ func (log *LOG) Value(msg *ctx.Message, arg ...interface{}) map[string]interface return nil } func (log *LOG) Log(msg *ctx.Message, action string, str string, arg ...interface{}) { - m := log.Message() - m.Capi("nlog", 1) - - args := kit.Trans(arg...) - for _, v := range []string{action, "bench"} { - for i := len(args); i >= 0; i-- { - if value := log.Value(m, append([]string{v}, args[:i]...)); kit.Right(value) && kit.Right(value["file"]) { - name := path.Join(m.Conf("logdir"), kit.Format(value["file"])) - file, ok := log.file[name] - if !ok { - if f, e := os.Create(name); e == nil { - file, log.file[name] = f, f - kit.Log("error", "%s log file %s", "open", name) - } else { - kit.Log("error", "%s log file %s %s", "open", name, e) - continue - } - } - - fmt.Fprintln(file, fmt.Sprintf("%d %s %s%s %s%s", m.Capi("nout", 1), msg.Format(value["meta"].([]interface{})...), - kit.Format(value["color_begin"]), action, fmt.Sprintf(str, arg...), kit.Format(value["color_end"]))) - return - } + if log.queue != nil { + log.queue <- map[string]interface{}{ + "action": action, + "str": str, + "arg": arg, + "msg": msg, } } } @@ -69,19 +53,55 @@ func (log *LOG) Spawn(m *ctx.Message, c *ctx.Context, arg ...string) ctx.Server return s } func (log *LOG) Begin(m *ctx.Message, arg ...string) ctx.Server { + return log +} +func (log *LOG) Start(m *ctx.Message, arg ...string) bool { log.file = map[string]*os.File{} - os.Mkdir(m.Conf("logdir"), 0770) + + os.MkdirAll(m.Conf("logdir"), 0770) kit.Log("error", "make log dir %s", m.Conf("logdir")) + ioutil.WriteFile(m.Conf("logpid"), []byte(kit.Format(os.Getpid())), 0666) kit.Log("error", "save log file %s", m.Conf("logpid")) + log.queue = make(chan map[string]interface{}, 1024) for _, v := range []string{"error", "bench", "debug"} { log.Log(m, v, "hello world\n") log.Log(m, v, "hello world") } - return log -} -func (log *LOG) Start(m *ctx.Message, arg ...string) bool { + m.Cap("stream", m.Conf("output", []string{"bench", "value", "file"})) + + for { + select { + case l := <-log.queue: + m.Capi("nlog", 1) + msg := l["msg"].(*ctx.Message) + + args := kit.Trans(l["arg"].([]interface{})...) + loop: + for _, v := range []string{kit.Format(l["action"]), "bench"} { + for i := len(args); i >= 0; i-- { + if value := log.Value(m, append([]string{v}, args[:i]...)); kit.Right(value) && kit.Right(value["file"]) { + name := path.Join(m.Conf("logdir"), kit.Format(value["file"])) + file, ok := log.file[name] + if !ok { + if f, e := os.Create(name); e == nil { + file, log.file[name] = f, f + kit.Log("error", "%s log file %s", "open", name) + } else { + kit.Log("error", "%s log file %s %s", "open", name, e) + continue + } + } + + fmt.Fprintln(file, fmt.Sprintf("%d %s %s%s %s%s", m.Capi("nout", 1), msg.Format(value["meta"].([]interface{})...), + kit.Format(value["color_begin"]), kit.Format(l["action"]), fmt.Sprintf(kit.Format(l["str"]), l["arg"].([]interface{})...), kit.Format(value["color_end"]))) + break loop + } + } + } + } + } return false } func (log *LOG) Close(m *ctx.Message, arg ...string) bool { @@ -122,6 +142,10 @@ var Index = &ctx.Context{Name: "log", Help: "日志中心", }, Help: "日志输出配置"}, }, Commands: map[string]*ctx.Command{ + "init": &ctx.Command{Name: "init", Help: "启动日志", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { + m.Target().Start(m) + return + }}, "log": &ctx.Command{Name: "log level string...", Help: "输出日志, level: 日志类型, string: 日志内容", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { if log, ok := m.Target().Server.(*LOG); m.Assert(ok) { log.Log(m, arg[0], arg[1], arg[2:]) diff --git a/src/contexts/nfs/nfs.go b/src/contexts/nfs/nfs.go index 8aa52ed6..caab65df 100644 --- a/src/contexts/nfs/nfs.go +++ b/src/contexts/nfs/nfs.go @@ -31,7 +31,6 @@ type NFS struct { out *os.File send chan *ctx.Message - recv chan *ctx.Message hand map[int]*ctx.Message *ctx.Context @@ -311,31 +310,29 @@ func (nfs *NFS) Term(msg *ctx.Message, action string, args ...interface{}) *NFS nfs.Term(m, "print", m.Conf("prompt")) case "print": - if m.Caps("termbox") { - for _, v := range kit.Format(args...) { - if x < right && y < bottom { - termbox.SetCell(x, y, v, fg, bg) - } + for _, v := range kit.Format(args...) { + if x < right && y < bottom { + termbox.SetCell(x, y, v, fg, bg) + } - if v > 255 { - x++ - } - if x++; v == '\n' || (x >= right && m.Confs("term", "wrap")) { - x, y = left, y+1 - } + if v > 255 { + x++ + } + if x++; v == '\n' || (x >= right && m.Confs("term", "wrap")) { + x, y = left, y+1 + } - if x < right && y < bottom { - m.Conf("term", "cursor_x", x) - m.Conf("term", "cursor_y", y) - termbox.SetCursor(x, y) - } + if x < right && y < bottom { + m.Conf("term", "cursor_x", x) + m.Conf("term", "cursor_y", y) + termbox.SetCursor(x, y) + } - if y >= bottom { - if !m.Options("scroll") { - nfs.Term(m, "scroll") - } - break + if y >= bottom { + if !m.Options("scroll") { + nfs.Term(m, "scroll") } + break } } case "color": @@ -460,6 +457,7 @@ func (nfs *NFS) Read(p []byte) (n int, err error) { case termbox.KeyCtrlC: nfs.Term(m, "exit") + n = copy(p, []byte("return\n")) return case termbox.KeyCtrlE: @@ -572,16 +570,14 @@ func (nfs *NFS) Read(p []byte) (n int, err error) { func (nfs *NFS) printf(arg ...interface{}) *NFS { m := nfs.Context.Message() - line := kit.Format(arg...) - if !strings.HasSuffix(line, "\n") { - line += "\n" - } + line := strings.TrimRight(kit.Format(arg...), "\n") m.Log("debug", "noutput %s", m.Cap("noutput", m.Capi("noutput")+1)) m.Confv("output", -2, map[string]interface{}{"time": time.Now().Unix(), "line": line}) if m.Caps("termbox") { nfs.Term(m, "clear").Term(m, "print", line).Term(m, "flush") - m.Conf("term", "prompt_y", m.Confi("term", "cursor_y")) + m.Conf("term", "prompt_y", m.Confi("term", "cursor_y")+1) + m.Conf("term", "cursor_y", m.Confi("term", "cursor_y")+1) } else { nfs.out.WriteString(line) } @@ -589,8 +585,11 @@ func (nfs *NFS) printf(arg ...interface{}) *NFS { } func (nfs *NFS) prompt(arg ...interface{}) *NFS { m := nfs.Context.Message() - target, _ := m.Optionv("ps_target").(*ctx.Context) + if target == nil { + target = nfs.Context + } + line := fmt.Sprintf("%d[%s]%s> ", m.Capi("ninput"), time.Now().Format("15:04:05"), target.Name) m.Conf("prompt", line) @@ -598,7 +597,7 @@ func (nfs *NFS) prompt(arg ...interface{}) *NFS { if m.Caps("termbox") { m.Conf("term", "prompt_y", m.Conf("term", "cursor_y")) nfs.Term(m, "clear").Term(m, "print", line).Term(m, "flush") - } else { + } else if nfs.out != nil { nfs.out.WriteString(line) } return nfs @@ -642,6 +641,32 @@ func (nfs *NFS) shadow(args ...interface{}) *NFS { return nfs } +func (nfs *NFS) Send(meta string, arg ...interface{}) *NFS { + m := nfs.Context.Message() + + n, e := fmt.Fprintf(nfs.io, "%s: %s\n", url.QueryEscape(meta), url.QueryEscape(kit.Format(arg[0]))) + m.Assert(e) + m.Capi("nwrite", n) + return nfs +} +func (nfs *NFS) Recv(line string) (field string, value string) { + m := nfs.Context.Message() + + m.Log("recv", "%d [%s]", len(line), line) + m.Capi("nread", len(line)+1) + + word := strings.Split(line, ": ") + field, e := url.QueryUnescape(word[0]) + m.Assert(e) + if len(word) == 1 { + return + } + + value, e = url.QueryUnescape(word[1]) + m.Assert(e) + return +} + func (nfs *NFS) Spawn(m *ctx.Message, c *ctx.Context, arg ...string) ctx.Server { if len(arg) > 0 && (arg[0] == "scan" || arg[0] == "open" || arg[0] == "append") { c.Caches = map[string]*ctx.Cache{ @@ -703,11 +728,19 @@ func (nfs *NFS) Start(m *ctx.Message, arg ...string) bool { line, bio := "", bufio.NewScanner(nfs) for nfs.prompt(); !m.Options("scan_end"); nfs.prompt() { for bio.Scan() { - if line = line + bio.Text(); !strings.HasSuffix(line, "\\") { + if text := bio.Text(); text == "" { + continue + } else if !strings.HasSuffix(text, "\\") { + line += text break + } else { + line += strings.TrimSuffix(text, "\\") } - line = strings.TrimSuffix(line, "\\") } + if line == "" { + line = "return" + } + m.Log("debug", "%s %d %d [%s]", "input", m.Capi("ninput", 1), len(line), line) m.Confv("input", -2, map[string]interface{}{"time": time.Now().Unix(), "line": line}) @@ -726,108 +759,73 @@ func (nfs *NFS) Start(m *ctx.Message, arg ...string) bool { } line = "" } - - if !m.Options("scan_end") { - m.Backs(m.Spawn(m.Source()).Set("detail", "return")) - } - return true + return false } - m.Cap("stream", m.Option("stream")) + m.Cap("stream", m.Option("ms_source")) nfs.io = m.Optionv("io").(io.ReadWriter) - nfs.hand = map[int]*ctx.Message{} nfs.send = make(chan *ctx.Message, 10) - nfs.recv = make(chan *ctx.Message, 10) + nfs.hand = map[int]*ctx.Message{} go func() { //发送消息队列 for { select { case msg := <-nfs.send: - head, body := "detail", "option" - if msg.Hand { - head, body = "result", "append" - send_code := msg.Option("send_code") - msg.Append("send_code1", send_code) - m.Log("info", "%s recv: %v %v", msg.Option("recv_code"), msg.Meta[head], msg.Meta[body]) - } else { - msg.Option("send_code", m.Capi("nsend", 1)) - m.Log("info", "%d send: %v %v", m.Capi("nsend"), msg.Meta[head], msg.Meta[body]) - nfs.hand[m.Capi("nsend")] = msg + code, meta, body := "0", "detail", "option" + if msg.Options("remote_code") { // 发送响应 + code, meta, body = msg.Option("remote_code"), "result", "append" + } else { // 发送请求 + code = kit.Format(m.Capi("nsend", 1)) + nfs.hand[kit.Int(code)] = msg } - for _, v := range msg.Meta[head] { - n, e := fmt.Fprintf(nfs.io, "%s: %s\n", head, url.QueryEscape(v)) - m.Assert(e) - m.Capi("nwrite", n) + nfs.Send("code", code) + for _, v := range msg.Meta[meta] { + nfs.Send(meta, v) } for _, k := range msg.Meta[body] { for _, v := range msg.Meta[k] { - n, e := fmt.Fprintf(nfs.io, "%s: %s\n", url.QueryEscape(k), url.QueryEscape(v)) - m.Assert(e) - m.Capi("nwrite", n) + nfs.Send(k, v) } } - - n, e := fmt.Fprintf(nfs.io, "\n") - m.Assert(e) - m.Capi("nwrite", n) } } }() - go func() { //接收消息队列 - var e error - var msg *ctx.Message - head, body := "", "" + //接收消息队列 + msg, code, head, body := m, "0", "result", "append" + for bio := bufio.NewScanner(nfs.io); bio.Scan(); { - for bio := bufio.NewScanner(nfs.io); bio.Scan(); { - if msg == nil { - msg = m.Sess("target") - } - if msg.Meta == nil { - msg.Meta = map[string][]string{} - } - line := bio.Text() - m.Log("recv", "(%s) %s", head, line) - m.Capi("nread", len(line)+1) - if len(line) == 0 { - if head == "detail" { - m.Log("info", "%d recv: %v %v %v", m.Capi("nrecv", 1), msg.Meta[head], msg.Meta[body], msg.Meta) - msg.Option("recv_code", m.Cap("nrecv")) - nfs.recv <- msg - } else { - m.Log("info", "%d send: %v %v %v", msg.Appendi("send_code1"), msg.Meta[head], msg.Meta[body], msg.Meta) - h := nfs.hand[msg.Appendi("send_code1")] - h.Copy(msg, "result").Copy(msg, "append") - h.Remote <- true - } - msg, head, body = nil, "", "append" - continue - } + switch field, value := nfs.Recv(bio.Text()); field { + case "code": + msg, code = m.Sess("ms_target"), value + msg.Meta = map[string][]string{} - word := strings.Split(line, ": ") - word[0], e = url.QueryUnescape(word[0]) - m.Assert(e) - word[1], e = url.QueryUnescape(word[1]) - m.Assert(e) - switch word[0] { - case "detail": - head, body = "detail", "option" - msg.Add(word[0], word[1]) - case "result": - head, body = "result", "append" - msg.Add(word[0], word[1]) - default: - msg.Add(body, word[0], word[1]) + case "detail": + head, body = "detail", "option" + msg.Add(field, value) + + case "result": + head, body = "result", "append" + msg.Add(field, value) + + case "": + if head == "detail" { // 接收请求 + msg.Option("remote_code", code) + msg.Call(func(sub *ctx.Message) *ctx.Message { + nfs.send <- msg.Copy(sub, "append").Copy(sub, "result") + return nil + }) + } else { // 接收响应 + h := nfs.hand[kit.Int(code)] + h.Copy(msg, "result").Copy(msg, "append").Back(h) } + msg, code, head, body = nil, "0", "result", "append" + + default: + msg.Add(body, field, value) } - }() - for { - select { - case msg := <-nfs.recv: - nfs.send <- msg.Cmd() - } } return true @@ -1237,7 +1235,7 @@ var Index = &ctx.Context{Name: "nfs", Help: "存储中心", if help := fmt.Sprintf("scan %s", arg[0]); arg[0] == "stdio" { m.Put("option", "in", os.Stdin).Put("option", "out", os.Stdout).Start(arg[0], help, key, arg[0]) } else if p, f, e := open(m, arg[0]); m.Assert(e) { - m.Put("option", "in", f).Start(fmt.Sprintf("file%s", m.Capi("nfile")), help, key, p) + m.Put("option", "in", f).Start(fmt.Sprintf("file%d", m.Capi("nfile", 1)), help, key, p) } } return @@ -1263,44 +1261,19 @@ var Index = &ctx.Context{Name: "nfs", Help: "存储中心", return }}, - "listen": &ctx.Command{Name: "listen args...", Help: "启动文件服务, args: 参考tcp模块, listen命令的参数", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { + "remote": &ctx.Command{Name: "remote listen|dial args...", Help: "启动文件服务, args: 参考tcp模块, listen命令的参数", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { if _, ok := m.Target().Server.(*NFS); m.Assert(ok) { //{{{ m.Sess("tcp").Call(func(sub *ctx.Message) *ctx.Message { + sub.Sess("ms_target", m.Source()) sub.Start(fmt.Sprintf("file%d", m.Capi("nfile", 1)), "远程文件") - - return sub.Sess("target", m.Source()).Call(func(sub1 *ctx.Message) *ctx.Message { - nfs, _ := sub.Target().Server.(*NFS) - sub1.Remote = make(chan bool, 1) - nfs.send <- sub1 - <-sub1.Remote - return nil - }) - }, m.Meta["detail"]) + return sub + }, arg) } return }}, - "dial": &ctx.Command{Name: "dial args...", Help: "连接文件服务, args: 参考tcp模块, dial命令的参数", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { - if _, ok := m.Target().Server.(*NFS); m.Assert(ok) { - m.Sess("tcp").Call(func(sub *ctx.Message) *ctx.Message { - sub.Start(fmt.Sprintf("file%d", m.Capi("nfile", 1)), "远程文件") - - return sub.Sess("target", m.Source()).Call(func(sub1 *ctx.Message) *ctx.Message { - nfs, _ := sub.Target().Server.(*NFS) - sub1.Remote = make(chan bool, 1) - nfs.send <- sub1 - <-sub1.Remote - return nil - }) - }, m.Meta["detail"]) - } - - return - }}, "send": &ctx.Command{Name: "send [file] args...", Help: "连接文件服务, args: 参考tcp模块, dial命令的参数", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { if nfs, ok := m.Target().Server.(*NFS); m.Assert(ok) && nfs.io != nil { - m.Remote = make(chan bool, 1) - nfs.send <- m - <-m.Remote + nfs.send <- m.Set("detail", arg) } return }}, diff --git a/src/contexts/ssh/ssh.go b/src/contexts/ssh/ssh.go index dcd35394..6ed3e7d0 100644 --- a/src/contexts/ssh/ssh.go +++ b/src/contexts/ssh/ssh.go @@ -2,8 +2,8 @@ package ssh import ( "contexts/ctx" - "fmt" "strings" + "toolkit" ) type SSH struct { @@ -37,32 +37,52 @@ var Index = &ctx.Context{Name: "ssh", Help: "集群中心", "domain": &ctx.Cache{Name: "domain", Value: "", Help: "主机域名"}, }, Configs: map[string]*ctx.Config{ + "host": &ctx.Config{Name: "host", Value: map[string]interface{}{}, Help: "主机数量"}, + "hostname": &ctx.Config{Name: "hostname", Value: "com", Help: "主机数量"}, "domain.json": &ctx.Config{Name: "domain.json", Value: "var/domain.json", Help: "主机数量"}, "domain.png": &ctx.Config{Name: "domain.png", Value: "var/domain.png", Help: "主机数量"}, }, Commands: map[string]*ctx.Command{ - "listen": &ctx.Command{Name: "listen address [security [protocol]]", Help: "网络监听", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { - m.Sess("nfs").Call(func(sub *ctx.Message) *ctx.Message { - sub.Start(fmt.Sprintf("host%d", m.Capi("nhost", 1)), "远程主机") - // sub.Spawn().Cmd("pwd", "") - return sub - }, m.Meta["detail"]) - - if !m.Caps("domain") { - m.Cap("domain", m.Cap("hostname", m.Conf("hostname"))) + "remote": &ctx.Command{Name: "remote listen|dial|send args...", Help: "网络监听", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { + if len(arg) == 0 { + m.Cmdy("ctx.config", "host") + return } - // m.Spawn(m.Target()).Cmd("save") + + host := m.Confm("host", arg[0]) + if host != nil { + arg = arg[1:] + } + + switch arg[0] { + case "listen", "dial": + m.Call(func(sub *ctx.Message) *ctx.Message { + h, _ := kit.Hash("host", m.Option("ms_source"), "uniq") + m.Log("fuck", "what %v", sub.Format()) + m.Confv("host", h, map[string]interface{}{ + "module": sub.Cap("module"), + "type": arg[0], + }) + return nil + }, "nfs.remote", arg) + + case "exec": + m.Find(kit.Format(host["module"]), true).CallBack(true, func(sub *ctx.Message) *ctx.Message { + m.Copy(sub) + return nil + }, arg[1:]) + } + return }}, - "dial": &ctx.Command{Name: "dial address [security [protocol]]", Help: "网络连接", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { - m.Sess("nfs").CallBack(true, func(sub *ctx.Message) *ctx.Message { - sub.Target().Start(sub) - return sub - }, m.Meta["detail"]) + + "demo": &ctx.Command{Name: "demo", Help: "远程执行", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { + m.Echo("demo") return }}, + "send": &ctx.Command{Name: "send [domain str] cmd arg...", Help: "远程执行", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { if ssh, ok := m.Target().Server.(*SSH); m.Assert(ok) { origin, domain := "", "" @@ -138,6 +158,7 @@ var Index = &ctx.Context{Name: "ssh", Help: "集群中心", } return }}, + "pwd": &ctx.Command{Name: "pwd [hostname]", Help: "主机域名", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { if len(arg) == 0 { m.Echo(m.Cap("domain")) diff --git a/src/contexts/tcp/tcp.go b/src/contexts/tcp/tcp.go index 97c848fc..fa77f365 100644 --- a/src/contexts/tcp/tcp.go +++ b/src/contexts/tcp/tcp.go @@ -79,8 +79,10 @@ func (tcp *TCP) Start(m *ctx.Message, arg ...string) bool { m.Log("info", "%s dial %s", m.Cap("nclient"), m.Cap("stream", fmt.Sprintf("%s->%s", tcp.LocalAddr(), tcp.RemoteAddr()))) + m.Option("ms_source", tcp.Context.Name) m.Put("option", "io", tcp).Back(m.Spawn(m.Source())) return false + case "accept": c, e := m.Optionv("io").(net.Conn) m.Assert(e) @@ -89,9 +91,11 @@ func (tcp *TCP) Start(m *ctx.Message, arg ...string) bool { m.Log("info", "%s accept %s", m.Cap("nclient"), m.Cap("stream", fmt.Sprintf("%s<-%s", tcp.LocalAddr(), tcp.RemoteAddr()))) + m.Option("ms_source", tcp.Context.Name) m.Put("option", "io", tcp).Back(m.Spawn(m.Source())) return false - default: + + case "listen": if m.Caps("security") { m.Sess("aaa", m.Sess("aaa").Cmd("login", "cert", m.Cap("certfile"), "key", m.Cap("keyfile"), "tcp")) cert, e := tls.LoadX509KeyPair(m.Cap("certfile"), m.Cap("keyfile")) diff --git a/src/contexts/yac/yac.go b/src/contexts/yac/yac.go index 707fd3aa..f31cf257 100644 --- a/src/contexts/yac/yac.go +++ b/src/contexts/yac/yac.go @@ -224,7 +224,6 @@ func (yac *YAC) parse(m *ctx.Message, out *ctx.Message, page int, void int, line } else if !m.Confs("exec", []string{yac.hand[hash], "disable"}) { //执行命令 msg := out.Spawn(m.Source()).Add("detail", yac.hand[hash], word) if m.Back(msg); msg.Hand { //命令替换 - m.Assert(!msg.Has("return")) word = msg.Meta["result"] } } @@ -249,6 +248,7 @@ func (yac *YAC) Begin(m *ctx.Message, arg ...string) ctx.Server { } func (yac *YAC) Start(m *ctx.Message, arg ...string) (close bool) { if len(arg) > 0 && arg[0] == "scan" { + m.Cap("stream", arg[1]) m.Sess("nfs").Call(func(input *ctx.Message) *ctx.Message { _, word, _ := yac.parse(m, input, m.Optioni("page"), m.Optioni("void"), input.Detail(0)+"\n", 1) input.Result(0, word) @@ -341,6 +341,9 @@ var Index = &ctx.Context{Name: "yac", Help: "语法中心", yac.mat = make([]map[byte]*State, m.Confi("info", "nlang")) yac.state = map[State]*State{} + if len(arg) > 0 { + yac.lex = m.Sess(arg[0]) + } m.Confm("seed", func(line int, seed map[string]interface{}) { m.Spawn().Cmd("train", seed["page"], seed["hash"], seed["word"]) }) @@ -386,14 +389,22 @@ var Index = &ctx.Context{Name: "yac", Help: "语法中心", } return }}, - "scan": &ctx.Command{Name: "scan filename", Help: "解析文件", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { + "scan": &ctx.Command{Name: "scan filename modulename", Help: "解析文件", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { if yac, ok := m.Target().Server.(*YAC); m.Assert(ok) { m.Optioni("page", yac.page["line"]) m.Optioni("void", yac.page["void"]) - if len(arg) > 0 { - m.Start(fmt.Sprintf("parse%d", m.Capi("nparse", 1)), "parse", key, arg[0]) + + name := "" + if len(arg) > 1 { + name = arg[1] } else { - m.Start(fmt.Sprintf("parse%d", m.Capi("nparse", 1)), "parse") + name = fmt.Sprintf("parse%d", m.Capi("nparse", 1)) + } + + if len(arg) > 0 { + m.Start(name, "parse", key, arg[0]) + } else { + m.Start(name, "parse") } } return diff --git a/src/toolkit/kit.go b/src/toolkit/kit.go index 2fa342f3..18b9bb46 100644 --- a/src/toolkit/kit.go +++ b/src/toolkit/kit.go @@ -430,6 +430,21 @@ func Duration(arg ...string) time.Duration { return d } +func Action(cmd string, arg ...interface{}) string { + switch cmd { + case "time": + return Format(time.Now()) + case "rand": + return Format(rand.Int()) + case "uniq": + return Format(time.Now(), rand.Int()) + default: + if len(arg) > 0 { + return Format(arg...) + } + } + return cmd +} func Time(arg ...string) int { if len(arg) == 0 { return Int(time.Now()) @@ -483,21 +498,6 @@ func FileName(name string, meta ...string) string { return strings.Join(result, "") } -func Action(cmd string, arg ...interface{}) string { - switch cmd { - case "time": - return Format(time.Now()) - case "rand": - return Format(rand.Int()) - case "uniq": - return Format(time.Now(), rand.Int()) - default: - if len(arg) > 0 { - return Format(arg...) - } - } - return cmd -} func Check(e error) bool { if e != nil { panic(e)