diff --git a/base/cli/cli.go b/base/cli/cli.go index f697c814..ea02c007 100644 --- a/base/cli/cli.go +++ b/base/cli/cli.go @@ -14,6 +14,54 @@ import ( "strings" ) +func _system_run(m *ice.Message, cmd *exec.Cmd) { + 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.Warn(e != nil, "%v run: %s", nil, kit.Select(e.Error(), err.String())) + } else { + m.Cost("%v exit: %v", nil, cmd.ProcessState.ExitCode()) + } + m.Push("code", int(cmd.ProcessState.ExitCode())) + m.Echo(out.String()) +} +func _daemon_run(m *ice.Message, cmd *exec.Cmd, out, err string) { + if out != "" { + if f, p, e := kit.Create(out); m.Assert(e) { + m.Log_EXPORT("stdout", p) + cmd.Stdout = f + cmd.Stderr = f + } + } + if err != "" { + if f, p, e := kit.Create(err); m.Assert(e) { + m.Log_EXPORT("stderr", p) + cmd.Stderr = f + } + } + + cmd.Env = append(cmd.Env, fmt.Sprintf("PATH=%s", os.Getenv("PATH"))) + if e := cmd.Start(); m.Warn(e != nil, "%v start: %s", cmd.Args, e) { + return + } + + m.Rich("daemon", nil, kit.Dict(kit.MDB_NAME, cmd.Process.Pid, "status", "running")) + m.Echo("%d", cmd.Process.Pid) + + m.Gos(m, func(m *ice.Message) { + if e := cmd.Wait(); e != nil { + m.Warn(e != nil, "%v wait: %s", cmd.Args, e) + } else { + m.Cost("%v exit: %v", cmd.Args, cmd.ProcessState.ExitCode()) + m.Rich("daemon", nil, func(key string, value map[string]interface{}) { + value["status"] = "exited" + }) + } + }) +} + var Index = &ice.Context{Name: "cli", Help: "命令模块", Caches: map[string]*ice.Cache{}, Configs: map[string]*ice.Config{ @@ -91,56 +139,12 @@ var Index = &ice.Context{Name: "cli", Help: "命令模块", if len(cmd.Env) > 0 { m.Info("env: %s", cmd.Env) } - if m.Option("cmd_stdout") != "" { - if f, p, e := kit.Create(m.Option("cmd_stdout")); m.Assert(e) { - m.Info("stdout: %s", p) - cmd.Stdout = f - cmd.Stderr = f - } - } - if m.Option("cmd_stderr") != "" { - if f, p, e := kit.Create(m.Option("cmd_stderr")); m.Assert(e) { - m.Info("stderr: %s", p) - cmd.Stderr = f - } - } switch m.Option("cmd_type") { case "daemon": - // 守护进程 - cmd.Env = append(cmd.Env, fmt.Sprintf("PATH=%s", os.Getenv("PATH"))) - if e := cmd.Start(); e != nil { - m.Warn(e != nil, "%v start: %s", arg, e) - return - } - - m.Rich("daemon", nil, kit.Dict(kit.MDB_NAME, cmd.Process.Pid, "status", "running")) - m.Echo("%d", cmd.Process.Pid) - - m.Gos(m, func(m *ice.Message) { - if e := cmd.Wait(); e != nil { - m.Warn(e != nil, "%v wait: %s", arg, e) - } else { - m.Cost("%v exit: %v", arg, cmd.ProcessState.ExitCode()) - m.Rich("daemon", nil, func(key string, value map[string]interface{}) { - value["status"] = "exited" - }) - } - }) - + _daemon_run(m, cmd, m.Option("cmd_stdout"), m.Option("cmd_stderr")) default: - // 系统命令 - 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.Warn(e != nil, "%v run: %s", arg, kit.Select(e.Error(), err.String())) - } else { - m.Cost("%v exit: %v", arg, cmd.ProcessState.ExitCode()) - } - m.Push("code", int(cmd.ProcessState.ExitCode())) - m.Echo(out.String()) + _system_run(m, cmd) } }}, ice.CLI_DAEMON: {Name: "daemon", Help: "守护进程", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { diff --git a/base/web/favor.go b/base/web/favor.go index 7fb25837..fc4717a1 100644 --- a/base/web/favor.go +++ b/base/web/favor.go @@ -9,6 +9,59 @@ import ( "os" ) +var FAVOR = ice.Name("favor", Index) + +func _favor_list(m *ice.Message, favor, id string, fields ...string) { + if favor == "" { + m.Richs(FAVOR, nil, "*", func(key string, value map[string]interface{}) { + m.Push(key, value["meta"], []string{"time", "count"}) + m.Push("render", kit.Select("spide", kit.Value(value, "meta.render"))) + m.Push(FAVOR, kit.Value(value, "meta.name")) + }) + m.Sort(FAVOR) + return + } + + m.Richs(ice.WEB_FAVOR, nil, favor, func(key string, value map[string]interface{}) { + if id == "" { + m.Grows(ice.WEB_FAVOR, kit.Keys(kit.MDB_HASH, key), "", "", func(index int, value map[string]interface{}) { + m.Push("", value, fields) + }) + return + } + + m.Grows(ice.WEB_FAVOR, kit.Keys(kit.MDB_HASH, key), "id", id, func(index int, value map[string]interface{}) { + m.Push("detail", value) + m.Optionv("value", value) + m.Push("key", "render") + m.Push("value", m.Cmdx(m.Conf(ice.WEB_FAVOR, kit.Keys("meta.render", value["type"])))) + }) + }) +} +func _favor_create(m *ice.Message, name string) string { + favor := m.Rich(ice.WEB_FAVOR, nil, kit.Data(kit.MDB_NAME, name)) + m.Log_CREATE("favor", favor, "name", favor) + return favor +} +func _favor_insert(m *ice.Message, favor, kind, name, text string, extra ...string) { + index := m.Grow(ice.WEB_FAVOR, kit.Keys(kit.MDB_HASH, favor), kit.Dict( + kit.MDB_TYPE, kind, kit.MDB_NAME, name, kit.MDB_TEXT, text, + "extra", kit.Dict(extra), + )) + m.Richs(ice.WEB_FAVOR, nil, favor, func(key string, value map[string]interface{}) { + kit.Value(value, "meta.time", m.Time()) + }) + m.Log_INSERT("favor", favor, "index", index, "name", name, "text", text) + m.Echo("%d", index) +} + +func FavorInsert(m *ice.Message, favor, kind, name, text string, extra ...string) { + _favor_insert(m, favor, kind, name, text, extra...) +} +func FavorList(m *ice.Message, favor, id string, fields ...string) { + _favor_list(m, favor, id, fields...) +} + func init() { Index.Merge(&ice.Context{ Configs: map[string]*ice.Config{ @@ -78,13 +131,7 @@ func init() { } if len(arg) == 0 { - // 收藏门类 - m.Richs(ice.WEB_FAVOR, nil, "*", func(key string, value map[string]interface{}) { - m.Push(key, value["meta"], []string{"time", "count"}) - m.Push("render", kit.Select("spide", kit.Value(value, "meta.render"))) - m.Push("favor", kit.Value(value, "meta.name")) - }) - m.Sort("favor") + _favor_list(m, "", "") return } @@ -162,27 +209,13 @@ func init() { } m.Option("favor", arg[0]) - fields := []string{kit.MDB_TIME, kit.MDB_ID, kit.MDB_TYPE, kit.MDB_NAME, kit.MDB_TEXT} - if len(arg) > 1 && arg[1] == "extra" { - fields, arg = append(fields, arg[2:]...), arg[:1] - } if len(arg) < 3 { - m.Richs(ice.WEB_FAVOR, nil, arg[0], func(key string, value map[string]interface{}) { - if len(arg) < 2 { - // 收藏列表 - m.Grows(ice.WEB_FAVOR, kit.Keys(kit.MDB_HASH, key), "", "", func(index int, value map[string]interface{}) { - m.Push("", value, fields) - }) - return - } - // 收藏详情 - m.Grows(ice.WEB_FAVOR, kit.Keys(kit.MDB_HASH, key), "id", arg[1], func(index int, value map[string]interface{}) { - m.Push("detail", value) - m.Optionv("value", value) - m.Push("key", "render") - m.Push("value", m.Cmdx(m.Conf(ice.WEB_FAVOR, kit.Keys("meta.render", value["type"])))) - }) - }) + // 收藏列表 + fields := []string{kit.MDB_TIME, kit.MDB_ID, kit.MDB_TYPE, kit.MDB_NAME, kit.MDB_TEXT} + if len(arg) > 1 && arg[1] == "extra" { + fields, arg = append(fields, arg[2:]...), arg[:1] + } + _favor_list(m, arg[0], kit.Select("", arg, 1), fields...) return } @@ -191,24 +224,13 @@ func init() { favor = key }) == nil { // 创建收藏 - favor = m.Rich(ice.WEB_FAVOR, nil, kit.Data(kit.MDB_NAME, arg[0])) - m.Log(ice.LOG_CREATE, "favor: %s name: %s", favor, arg[0]) + favor = _favor_create(m, arg[0]) } if len(arg) == 3 { arg = append(arg, "") } - - // 添加收藏 - index := m.Grow(ice.WEB_FAVOR, kit.Keys(kit.MDB_HASH, favor), kit.Dict( - kit.MDB_TYPE, arg[1], kit.MDB_NAME, arg[2], kit.MDB_TEXT, arg[3], - "extra", kit.Dict(arg[4:]), - )) - m.Richs(ice.WEB_FAVOR, nil, favor, func(key string, value map[string]interface{}) { - kit.Value(value, "meta.time", m.Time()) - }) - m.Log(ice.LOG_INSERT, "favor: %s index: %d name: %s text: %s", arg[0], index, arg[2], arg[3]) - m.Echo("%d", index) + _favor_insert(m, favor, arg[1], arg[2], arg[3], arg[4:]...) // 分发数据 if p := kit.Select(m.Conf(ice.WEB_FAVOR, "meta.proxy"), m.Option("you")); p != "" { diff --git a/base/web/space.go b/base/web/space.go index 3a0c2f9a..39d838a1 100644 --- a/base/web/space.go +++ b/base/web/space.go @@ -100,6 +100,7 @@ func _space_send(m *ice.Message, space string, arg ...string) { m.Target().Server().(*Frame).send[id] = m socket.WriteMessage(1, []byte(m.Format("meta"))) + m.Option("timeout", m.Conf(SPACE, "meta.timeout.c")) m.Call(m.Option("_async") == "", func(res *ice.Message) *ice.Message { if res != nil && m != nil { // 返回结果 @@ -137,9 +138,7 @@ func init() { }) case "connect": - dev := kit.Select("dev", arg, 1) - name := kit.Select(m.Conf(ice.CLI_RUNTIME, "node.name"), arg, 2) - _space_dial(m, dev, name) + _space_dial(m, kit.Select("dev", arg, 1), kit.Select(m.Conf(ice.CLI_RUNTIME, "node.name"), arg, 2)) default: if len(arg) == 1 { @@ -168,7 +167,6 @@ func init() { if m.Richs(ice.WEB_SHARE, nil, share, nil) == nil { share = m.Cmdx(ice.WEB_SHARE, "add", m.Option("node"), m.Option("name"), m.Option("user")) } - // m.Cmd(ice.WEB_GROUP, m.Option("group"), "add", m.Option("name")) // 添加节点 h := m.Rich(ice.WEB_SPACE, nil, kit.Dict( diff --git a/base/web/web.go b/base/web/web.go index 78d92892..9526b98c 100644 --- a/base/web/web.go +++ b/base/web/web.go @@ -175,6 +175,8 @@ func (web *Frame) HandleWSS(m *ice.Message, safe bool, c *websocket.Conn, name s // 本地执行 m.Option("_dev", name) msg = msg.Cmd() + msg.Set("_option") + msg.Set("_option") } if source, target = []string{}, kit.Revert(source)[1:]; msg.Detail() == "exit" { // 重启进程 diff --git a/core/wiki/inner.go b/core/wiki/inner.go index cd83d93b..834eaabf 100644 --- a/core/wiki/inner.go +++ b/core/wiki/inner.go @@ -94,6 +94,7 @@ func _inner_show(m *ice.Message, name string) { if ls := kit.Simple(m.Confv(INNER, kit.Keys("meta.show", p))); len(ls) > 0 { m.Cmdy(ice.CLI_SYSTEM, ls, name) m.Set(ice.MSG_APPEND) + m.Cmd(web.FAVOR, "inner.run", "shell", name, m.Result()) return } @@ -170,6 +171,9 @@ func init() { "run": {Name: "run path name", Help: "运行", Hand: func(m *ice.Message, arg ...string) { _inner_show(m, path.Join("./", arg[0], arg[1])) }}, + "log": {Name: "log path name", Help: "日志", Hand: func(m *ice.Message, arg ...string) { + web.FavorList(m, "inner.run", "", "time", "id", "type", "name", "text") + }}, "plug": {Name: "plug path name", Help: "插件", Hand: func(m *ice.Message, arg ...string) { _inner_plug(m, path.Join("./", arg[0], arg[1])) }}, diff --git a/type.go b/type.go index 9b89f632..408815c5 100644 --- a/type.go +++ b/type.go @@ -9,7 +9,6 @@ import ( kit "github.com/shylinux/toolkits" "encoding/json" - "errors" "fmt" "io" "net/http" @@ -387,115 +386,6 @@ func (m *Message) Spawn(arg ...interface{}) *Message { return msg } -func (m *Message) TryCatch(msg *Message, safe bool, hand ...func(msg *Message)) *Message { - defer func() { - switch e := recover(); e { - case io.EOF: - case nil: - default: - _, file, line, _ := runtime.Caller(3) - if list := strings.Split(file, "/"); len(list) > 2 { - file = strings.Join(list[len(list)-2:], "/") - } - m.Log(LOG_WARN, "catch: %s %s:%d", e, file, line) - m.Log(LOG_INFO, "chain: %s", msg.Format("chain")) - m.Log(LOG_WARN, "catch: %s %s:%d", e, file, line) - m.Log(LOG_INFO, "stack: %s", msg.Format("stack")) - if m.Log(LOG_WARN, "catch: %s %s:%d", e, file, line); len(hand) > 1 { - // 捕获异常 - m.TryCatch(msg, safe, hand[1:]...) - } else if !safe { - // 抛出异常 - m.Assert(e) - } - } - }() - - if len(hand) > 0 { - // 运行函数 - hand[0](msg) - } - return m -} -func (m *Message) Assert(arg interface{}) bool { - switch arg := arg.(type) { - case nil: - return true - case bool: - if arg == true { - return true - } - } - - // 抛出异常 - panic(errors.New(fmt.Sprintf("error %v", arg))) -} -func (m *Message) Sleep(arg string) *Message { - time.Sleep(kit.Duration(arg)) - return m -} -func (m *Message) Hold(n int) *Message { - ctx := m.target.root - if c := m.target; c.context != nil && c.context.wg != nil { - ctx = c.context - } - - ctx.wg.Add(n) - m.Log(LOG_TRACE, "%s wait %s %v", ctx.Name, m.target.Name, ctx.wg) - return m -} -func (m *Message) Done() bool { - defer func() { recover() }() - - ctx := m.target.root - if c := m.target; c.context != nil && c.context.wg != nil { - ctx = c.context - } - - m.Log(LOG_TRACE, "%s done %s %v", ctx.Name, m.target.Name, ctx.wg) - ctx.wg.Done() - return true -} -func (m *Message) Call(sync bool, cb func(*Message) *Message) *Message { - wait := make(chan bool, 2) - t := time.AfterFunc(kit.Duration("10s"), func() { - m.Log(LOG_WARN, "timeout") - m.Back(nil) - wait <- false - }) - m.cb = func(sub *Message) *Message { - if sync { - t.Stop() - wait <- true - } - return cb(sub) - } - - if sync { - <-wait - } else { - t.Stop() - } - return m -} -func (m *Message) Back(res *Message) *Message { - if m.cb != nil { - // if res != nil { - // m.Info("back %v", res.Format("prefix")) - // } else { - // m.Info("back %v", nil) - // } - if sub := m.cb(res); m.message != nil { - m.message.Back(sub) - } - } - return m -} -func (m *Message) Gos(msg *Message, cb func(*Message)) *Message { - go func() { msg.TryCatch(msg, true, func(msg *Message) { cb(msg) }) }() - return m -} - func (m *Message) Run(arg ...string) *Message { m.target.server.Start(m, arg...) return m