diff --git a/src/contexts/ctx.go b/src/contexts/ctx.go index e1a061ff..2a637d41 100644 --- a/src/contexts/ctx.go +++ b/src/contexts/ctx.go @@ -199,6 +199,16 @@ func (c *Context) Begin(m *Message) *Context { // {{{ c.Caches["status"] = &Cache{Name: "服务状态(begin/start/close)", Value: "begin", Help: "服务状态,begin:初始完成,start:正在运行,close:未在运行"} c.Caches["stream"] = &Cache{Name: "服务数据", Value: "", Help: "服务数据"} + item := []string{} + m.BackTrace(func(m *Message) bool { + item = append(item, m.target.Name) + return true + }) + for i := 0; i < len(item)/2; i++ { + item[i], item[len(item)-i-1] = item[len(item)-i-1], item[i] + } + c.Caches["route"] = &Cache{Name: "服务数据", Value: strings.Join(item, "."), Help: "服务数据"} + m.Index = 1 c.Pulse = m c.Requests = []*Message{m} @@ -916,13 +926,24 @@ func (m *Message) Back(msg *Message) *Message { // {{{ } // }}} -func (m *Message) CallBack(cb func(msg *Message) (sub *Message), arg ...interface{}) *Message { // {{{ +func (m *Message) CallBack(sync bool, cb func(msg *Message) (sub *Message), arg ...interface{}) *Message { // {{{ + if !sync { + m.Call(cb, arg...) + return m + } + wait := make(chan bool) + go m.Call(func(sub *Message) *Message { + m.Log("lock", nil, "before done %v", arg) wait <- true + m.Log("lock", nil, "after done %v", arg) return cb(sub) }, arg...) + + m.Log("lock", nil, "before wait %v", arg) <-wait + m.Log("lock", nil, "after wait %v", arg) return m } @@ -1790,8 +1811,8 @@ var Index = &Context{Name: "ctx", Help: "模块中心", } // }}} }}, - "context": &Command{Name: "context back|[[home] [find|search] name] [info|list|show|spawn|start|switch|close][args]", Help: "查找并操作模块,\n查找起点root:根模块、back:父模块、home:本模块,\n查找方法find:路径匹配、search:模糊匹配,\n查找对象name:支持点分和正则,\n操作类型show:显示信息、switch:切换为当前、start:启动模块、spawn:分裂子模块,args:启动参数", - Formats: map[string]int{"back": 0, "home": 0, "find": 1, "search": 1, "info": 1, "list": 0, "show": 0, "close": 0, "switch": 0, "start": 0, "spawn": 0}, + "context": &Command{Name: "context back|[[home] [find|search] name] [info|list|show|switch|[args]", Help: "查找并操作模块,\n查找起点root:根模块、back:父模块、home:本模块,\n查找方法find:路径匹配、search:模糊匹配,\n查找对象name:支持点分和正则,\n操作类型show:显示信息、switch:切换为当前、start:启动模块、spawn:分裂子模块,args:启动参数", + Formats: map[string]int{"back": 0, "home": 0, "find": 1, "search": 1, "info": 1, "list": 0, "show": 0, "switch": 0}, Hand: func(m *Message, c *Context, key string, arg ...string) { if m.Has("back") { // {{{ m.target = m.source @@ -1826,14 +1847,6 @@ var Index = &Context{Name: "ctx", Help: "模块中心", switch { case m.Has("switch"), m.Has("back"): m.target = v.target - case m.Has("spawn"): - v.Set("detail", arg[2:]...).target.Spawn(v, arg[0], arg[1]).Begin(v) - m.target = v.target - case m.Has("start"): - v.Set("detail", arg...).target.Start(v) - m.target = v.target - case m.Has("close"): - v.target.Close(v) case m.Has("show"): m.Echo("%s(%s): %s\n", v.target.Name, v.target.Owner.Name, v.target.Help) if len(v.target.Requests) > 0 { @@ -1855,6 +1868,19 @@ var Index = &Context{Name: "ctx", Help: "模块中心", switch m.Get("info") { case "name": m.Echo("%s", v.target.Name) + case "path": + path := []string{} + m.BackTrace(func(m *Message) bool { + path = append(path, m.target.Name) + return true + }) + + list := []string{} + for i := len(path) - 1; i >= 0; i-- { + list = append(list, path[i]) + } + + m.Echo("%s", strings.Join(list, ".")) case "owner": m.Echo("%s", v.target.Owner.Name) default: diff --git a/src/contexts/nfs/nfs.go b/src/contexts/nfs/nfs.go index 4bcdb29e..ef67ea58 100644 --- a/src/contexts/nfs/nfs.go +++ b/src/contexts/nfs/nfs.go @@ -426,28 +426,37 @@ func (nfs *NFS) Begin(m *ctx.Message, arg ...string) ctx.Server { // {{{ // }}} func (nfs *NFS) Start(m *ctx.Message, arg ...string) bool { // {{{ m.Target().Sessions["nfs"] = m + m.Sessions["nfs"] = m nfs.Message = m if socket, ok := m.Data["io"]; ok { m.Cap("stream", m.Source().Name) // m.Sesss("aaa", "aaa").Cmd("login", "demo", "demo") + m.Options("stdio", false) nfs.io = socket.(io.ReadWriteCloser) nfs.Reader = bufio.NewReader(nfs.io) nfs.Writer = bufio.NewWriter(nfs.io) + nfs.send = make(map[int]*ctx.Message) nfs.target = m.Target() if target, ok := m.Data["target"]; ok { nfs.target = target.(*ctx.Context) } - msg := m.Spawn(nfs.target) - nfs.Caches["target"] = &ctx.Cache{Name: "target", Value: nfs.target.Name, Help: "文件名"} + var msg *ctx.Message + + nfs.Caches["target"] = &ctx.Cache{Name: "target", Value: "", Help: "文件名"} for { line, e := nfs.Reader.ReadString('\n') m.Assert(e) + if msg == nil { + msg = m.Sesss("ssh") + m.Cap("target", msg.Target().Name) + } + if line = strings.TrimSpace(line); len(line) > 0 { ls := strings.SplitN(line, ":", 2) ls[0] = strings.TrimSpace(ls[0]) @@ -466,7 +475,6 @@ func (nfs *NFS) Start(m *ctx.Message, arg ...string) bool { // {{{ } if msg.Has("detail") { - msg.Target(m.Sessions["ssh"].Target()) msg.Log("info", nil, "%d recv", m.Capi("nrecv", 1)) msg.Log("info", nil, "detail: %v", msg.Meta["detail"]) msg.Log("info", nil, "option: %v", msg.Meta["option"]) @@ -530,8 +538,7 @@ func (nfs *NFS) Start(m *ctx.Message, arg ...string) bool { // {{{ send.Back(send) } - msg = m.Spawn(nfs.target) - m.Cap("target", nfs.target.Name) + msg = nil } return true } diff --git a/src/contexts/ssh/ssh.go b/src/contexts/ssh/ssh.go index 6815c6f2..92a2e573 100644 --- a/src/contexts/ssh/ssh.go +++ b/src/contexts/ssh/ssh.go @@ -5,6 +5,7 @@ import ( // {{{ "fmt" "strings" + "time" ) // }}} @@ -12,12 +13,15 @@ import ( // {{{ type SSH struct { nfs *ctx.Context + *ctx.Message *ctx.Context } func (ssh *SSH) Spawn(m *ctx.Message, c *ctx.Context, arg ...string) ctx.Server { // {{{ c.Caches = map[string]*ctx.Cache{} - c.Configs = map[string]*ctx.Config{} + c.Configs = map[string]*ctx.Config{ + "domain": &ctx.Config{Name: "domain", Value: "", Help: "主机数量"}, + } s := new(SSH) s.Context = c @@ -35,6 +39,7 @@ func (ssh *SSH) Begin(m *ctx.Message, arg ...string) ctx.Server { // {{{ // }}} func (ssh *SSH) Start(m *ctx.Message, arg ...string) bool { // {{{ + ssh.Message = m ssh.nfs = m.Source() m.Cap("stream", m.Source().Name) return false @@ -78,9 +83,12 @@ var Index = &ctx.Context{Name: "ssh", Help: "集群中心", "count": &ctx.Cache{Name: "count", Value: "3", Help: "主机数量"}, "share": &ctx.Cache{Name: "share", Value: "root", Help: "主机数量"}, "level": &ctx.Cache{Name: "level", Value: "root", Help: "主机数量"}, + + "domain": &ctx.Cache{Name: "domain", Value: "com", Help: "主机数量"}, }, Configs: map[string]*ctx.Config{ - "route": &ctx.Config{Name: "route", Value: "com", Help: "主机数量"}, + "domain": &ctx.Config{Name: "domain", Value: "com", Help: "主机数量"}, + "route.json": &ctx.Config{Name: "route.json", Value: "var/route.json", Help: "主机数量"}, "route.png": &ctx.Config{Name: "route.png", Value: "var/route.png", Help: "主机数量"}, "type": &ctx.Config{Name: "type", Value: "terminal", Help: "主机数量"}, @@ -94,6 +102,7 @@ var Index = &ctx.Context{Name: "ssh", Help: "集群中心", m.Find("nfs").Call(func(file *ctx.Message) *ctx.Message { sub := file.Spawn(m.Target()) sub.Start(fmt.Sprintf("host%d", Pulse.Capi("nhost", 1)), "远程主机") + m.Sessions["ssh"] = sub // sub.Sesss("nfs").Cmd("send", "route", sub.Target().Name, m.Cap("route")) return sub }, m.Meta["detail"]) @@ -105,6 +114,10 @@ var Index = &ctx.Context{Name: "ssh", Help: "集群中心", m.Find("nfs").Call(func(file *ctx.Message) *ctx.Message { sub := file.Spawn(m.Target()) sub.Target().Start(sub) + m.Sessions["ssh"] = sub + + time.Sleep(time.Second) + sub.Spawn(sub.Target()).Cmd("pwd", m.Conf("domain")) return sub }, m.Meta["detail"]) } @@ -127,12 +140,29 @@ var Index = &ctx.Context{Name: "ssh", Help: "集群中心", }}, "who": &ctx.Command{Name: "who", Help: "远程执行", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { aaa := m.Sesss("aaa") - m.Echo(aaa.Cap("group")) + if aaa != nil { + m.Echo(aaa.Cap("group")) + } }}, "pwd": &ctx.Command{Name: "pwd", Help: "远程执行", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { - m.Echo(m.Cap("route")) // {{{ - m.Back(m) - // }}} + switch len(arg) { + case 0: + m.Echo(m.Cap("domain")) + case 1: + if m.Options("nsend") { + m.Conf("domain", arg[0]) + m.Echo(m.Cap("domain")) + m.Echo(".") + m.Echo(m.Conf("domain")) + } else { + m.Spawn(m.Target()).CallBack(m.Options("stdio"), func(msg *ctx.Message) *ctx.Message { + m.Conf("domain", msg.Result(2)) + m.Echo(m.Cap("domain", strings.Join(msg.Meta["result"], ""))) + m.Back(msg) + return nil + }, "send", "pwd", arg[0]) + } + } }}, "send": &ctx.Command{Name: "send [route domain] cmd arg...", Help: "远程执行", Formats: map[string]int{"route": 1}, @@ -140,15 +170,15 @@ var Index = &ctx.Context{Name: "ssh", Help: "集群中心", if ssh, ok := m.Target().Server.(*SSH); m.Assert(ok) { // {{{ target := strings.Split(m.Option("route"), ".") - if len(target) == 0 { + if len(target) == 1 && len(target[0]) == 0 { if m.Options("nsend") { msg := m.Spawn(m.Target()) msg.Cmd(arg) m.Back(msg) } else { - msg := m.Spawn(ssh.nfs) - msg.Call(func(host *ctx.Message) *ctx.Message { - return m.Copy(host, "result").Copy(host, "append") + ssh.Message.Sesss("nfs").CallBack(m.Options("stdio"), func(host *ctx.Message) *ctx.Message { + m.Back(m.Copy(host, "result").Copy(host, "option")) + return nil }, "send", "send", arg) } return