From 5c3a4d5eb412cd874396ab99f099c09b6b00b1ea Mon Sep 17 00:00:00 2001 From: shaoying Date: Tue, 8 Jan 2019 15:17:02 +0800 Subject: [PATCH] opt nfs --- src/contexts/cli/cli.go | 12 +- src/contexts/ctx/ctx.go | 103 ++++++++--- src/contexts/gdb/gdb.go | 5 - src/contexts/gdb/gdb_test.go | 28 +++ src/contexts/log/log.go | 26 ++- src/contexts/log/log_test.go | 19 ++ src/contexts/nfs/nfs.go | 338 ++++++++++++++++------------------- src/toolkit/kit.go | 22 +++ 8 files changed, 332 insertions(+), 221 deletions(-) create mode 100644 src/contexts/gdb/gdb_test.go create mode 100644 src/contexts/log/log_test.go diff --git a/src/contexts/cli/cli.go b/src/contexts/cli/cli.go index c867f3bc..0f003ede 100644 --- a/src/contexts/cli/cli.go +++ b/src/contexts/cli/cli.go @@ -77,7 +77,11 @@ func (cli *CLI) Start(m *ctx.Message, arg ...string) bool { m.Target().Close(m) } - m.Optionv("ps_target", cmd.Optionv("ps_target")) + v := cmd.Optionv("ps_target") + if v != nil { + m.Optionv("ps_target", v) + } + m.Set("append").Copy(cmd, "append") m.Set("result").Copy(cmd, "result") return nil @@ -203,7 +207,6 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心", if e := cmd.Run(); e != nil { m.Echo("error: ").Echo("%s\n", e).Echo(err.String()) - m.Log("trace", "%s\n", e) } else { switch m.Option("cmd_parse") { case "json": @@ -312,8 +315,8 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心", detail = append(detail, arg...) // 目标切换 + target := m.Optionv("ps_target") if detail[0] != "context" { - target := m.Optionv("ps_target") defer func() { m.Optionv("ps_target", target) }() } @@ -401,6 +404,9 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心", if msg.Set("detail", args).Cmd(); !msg.Hand { msg.Cmd("system", args) } + if msg.Appends("ps_target1") { + target = msg.Target() + } // 管道命令 if len(rest) > 0 { diff --git a/src/contexts/ctx/ctx.go b/src/contexts/ctx/ctx.go index 17a993ad..9c6066dc 100644 --- a/src/contexts/ctx/ctx.go +++ b/src/contexts/ctx/ctx.go @@ -4,8 +4,8 @@ import ( "encoding/json" "fmt" "html/template" - "io/ioutil" "regexp" + "runtime" "strconv" "strings" @@ -13,7 +13,6 @@ import ( "io" "math/rand" "os" - "runtime/debug" "sort" "time" "toolkit" @@ -171,7 +170,7 @@ func (c *Context) Close(m *Message, arg ...string) bool { return true } - m.Log("close", "%d:%d %v", len(c.requests), len(c.sessions), arg) + 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 { @@ -185,7 +184,7 @@ func (c *Context) Close(m *Message, arg ...string) bool { } } - m.Log("close", "%d:%d %v", len(c.requests), len(c.sessions), arg) + m.Log("close", "after %d:%d %v", len(c.requests), len(c.sessions), arg) if len(c.requests) > 0 { return false } @@ -307,17 +306,21 @@ func (m *Message) Log(action string, str string, arg ...interface{}) *Message { if l := m.Sess("log", false); l != nil { if log, ok := l.target.Server.(LOGGER); ok { + if action == "error" { + log.Log(m, "error", "chain: %s", m.Format("chain")) + } log.Log(m, action, str, arg...) if action == "error" { - log.Log(m, "error", "%s", m.Format("full")) - log.Log(m, "error", "%s\n\n", string(debug.Stack())) + log.Log(m, "error", "stack: %s", m.Format("stack")) } return m } } if action == "error" { + kit.Log("error", fmt.Sprintf("chain: %s", m.Format("chain"))) kit.Log("error", fmt.Sprintf("%s %s %s", m.Format(), action, fmt.Sprintf(str, arg...))) + kit.Log("error", fmt.Sprintf("stack: %s", m.Format("stack"))) } return m @@ -406,25 +409,56 @@ func (m *Message) Format(arg ...string) string { case "result": meta = append(meta, fmt.Sprintf("%v", m.Meta["result"])) case "full": - meta = append(meta, fmt.Sprintf("%s\n", m.Format("time", "ship"))) - meta = append(meta, fmt.Sprintf("detail: %d %v\n", len(m.Meta["detail"]), m.Meta["detail"])) - meta = append(meta, fmt.Sprintf("option: %d %v\n", len(m.Meta["option"]), m.Meta["option"])) - for _, k := range m.Meta["option"] { - if v, ok := m.Data[k]; ok { - meta = append(meta, fmt.Sprintf(" %s: %v\n", k, kit.Format(v))) - } else if v, ok := m.Meta[k]; ok { - meta = append(meta, fmt.Sprintf(" %s: %d %v\n", k, len(v), v)) + case "chain": + ms := []*Message{} + if v == "full" { + ms = append(ms, m) + } else { + for msg := m; msg != nil; msg = msg.message { + ms = append(ms, msg) } } - meta = append(meta, fmt.Sprintf("append: %d %v\n", len(m.Meta["append"]), m.Meta["append"])) - for _, k := range m.Meta["append"] { - if v, ok := m.Data[k]; ok { - meta = append(meta, fmt.Sprintf(" %s: %v\n", k, kit.Format(v))) - } else if v, ok := m.Meta[k]; ok { - meta = append(meta, fmt.Sprintf(" %s: %d %v\n", k, len(v), v)) + + for i := len(ms) - 1; i >= 0; i-- { + msg := ms[i] + + meta = append(meta, fmt.Sprintf("\n%s\n", msg.Format("time", "ship"))) + meta = append(meta, fmt.Sprintf(" detail: %d %v\n", len(msg.Meta["detail"]), msg.Meta["detail"])) + meta = append(meta, fmt.Sprintf(" option: %d %v\n", len(msg.Meta["option"]), msg.Meta["option"])) + for _, k := range msg.Meta["option"] { + if v, ok := msg.Data[k]; ok { + meta = append(meta, fmt.Sprintf(" %s: %v\n", k, kit.Format(v))) + } else if v, ok := msg.Meta[k]; ok { + meta = append(meta, fmt.Sprintf(" %s: %d %v\n", k, len(v), v)) + } + } + meta = append(meta, fmt.Sprintf(" append: %d %v\n", len(msg.Meta["append"]), msg.Meta["append"])) + for _, k := range msg.Meta["append"] { + if v, ok := msg.Data[k]; ok { + meta = append(meta, fmt.Sprintf(" %s: %v\n", k, kit.Format(v))) + } else if v, ok := msg.Meta[k]; ok { + meta = append(meta, fmt.Sprintf(" %s: %d %v\n", k, len(v), v)) + } + } + meta = append(meta, fmt.Sprintf(" result: %d %v\n", len(msg.Meta["result"]), msg.Meta["result"])) + } + case "stack": + pc := make([]uintptr, 100) + pc = pc[:runtime.Callers(2, pc)] + frames := runtime.CallersFrames(pc) + + for { + frame, more := frames.Next() + file := strings.Split(frame.File, "/") + name := strings.Split(frame.Function, "/") + meta = append(meta, fmt.Sprintf("\n%s:%d\t%s", file[len(file)-1], frame.Line, name[len(name)-1])) + if !more { + break } } - meta = append(meta, fmt.Sprintf("result: %d %v\n", len(m.Meta["result"]), m.Meta["result"])) + + default: + meta = append(meta, kit.FileName(v, "time")) } } return strings.Join(meta, " ") @@ -1140,9 +1174,11 @@ func (m *Message) TryCatch(msg *Message, safe bool, hand ...func(msg *Message)) case io.EOF: case nil: default: - m.Log("stack", "m: %s", m.Format("full")) - m.Log("stack", "msg: %s", msg.Format("full")) - m.Log("stack", "%s\n%s\n", e, string(debug.Stack())) + m.Log("bench", "chain: %s", msg.Format("chain")) + m.Log("bench", "catch: %s", e) + m.Log("bench", "stack: %s", msg.Format("stack")) + + m.Log("error", "catch: %s", e) if len(hand) > 1 { m.TryCatch(msg, safe, hand[1:]...) @@ -1619,6 +1655,19 @@ var Index = &Context{Name: "ctx", Help: "模块中心", Server: &CTX{}, } } + if len(arg) > 0 { + switch arg[0] { + case "full": + m.Echo(m.Format("full")) + return + case "back": + m.Echo(m.Format("back")) + return + case "stack": + m.Echo(m.Format("stack")) + return + } + } if len(arg) > 0 && arg[0] == "spawn" { sub := msg.Spawn() m.Echo("%d", sub.code) @@ -1986,7 +2035,9 @@ var Index = &Context{Name: "ctx", Help: "模块中心", Server: &CTX{}, msg.target.Start(msg, arg...) m.Copy(msg, "append").Copy(msg, "result").Copy(msg, "target") case "close": - msg.target.Close(msg, arg...) + msg := m.Spawn() + m.target = msg.target.context + msg.target.Close(msg.target.message, arg...) } } @@ -3227,8 +3278,6 @@ func Start(args ...string) bool { args = append(args, os.Args[1:]...) } - ioutil.WriteFile(fmt.Sprintf("bench.pid"), []byte(kit.Format(os.Getpid())), 0666) - Index.Begin(Pulse, args...) Index.Start(Pulse, args...) Index.Close(Pulse, args...) diff --git a/src/contexts/gdb/gdb.go b/src/contexts/gdb/gdb.go index 0a10816e..d32618cd 100644 --- a/src/contexts/gdb/gdb.go +++ b/src/contexts/gdb/gdb.go @@ -4,8 +4,6 @@ import ( "contexts/ctx" "toolkit" - "fmt" - "io/ioutil" "os" "os/signal" "syscall" @@ -84,10 +82,7 @@ func (gdb *GDB) Begin(m *ctx.Message, arg ...string) ctx.Server { func (gdb *GDB) Start(m *ctx.Message, arg ...string) bool { gdb.goon = make(chan os.Signal, 10) gdb.wait = make(chan interface{}, 10) - m.Log("error", "pid %d", os.Getpid()) - kit.Log("error", "pid %d", os.Getpid()) signal.Notify(gdb.goon, syscall.Signal(19)) - ioutil.WriteFile(fmt.Sprintf("%s.pid", gdb.Name), []byte(kit.Format(os.Getpid())), 0666) for { select { case sig := <-gdb.goon: diff --git a/src/contexts/gdb/gdb_test.go b/src/contexts/gdb/gdb_test.go new file mode 100644 index 00000000..c6837a76 --- /dev/null +++ b/src/contexts/gdb/gdb_test.go @@ -0,0 +1,28 @@ +package gdb + +import ( + "contexts/ctx" + "testing" + "time" +) + +func TestLog(t *testing.T) { + m := ctx.Pulse.Spawn(Index) + m.Sess("gdb", m) + m.Target().Begin(m).Start(m) + + go func() { + t.Logf("%s", m.Cmd("wait", "config", "demo").Result(0)) + + // t.Logf("%s", m.Cmd("demo", "what").Result(0)) + }() + + time.Sleep(time.Second * 3) + + m.Spawn().Cmd("goon", "nice") + + // gdb := m.Target().Server.(*GDB) + // gdb.Goon("yes", "command", "demo") + // + time.Sleep(time.Second * 3) +} diff --git a/src/contexts/log/log.go b/src/contexts/log/log.go index 449b9860..14e4f884 100644 --- a/src/contexts/log/log.go +++ b/src/contexts/log/log.go @@ -2,6 +2,7 @@ package log import ( "contexts/ctx" + "io/ioutil" "path" "toolkit" @@ -68,8 +69,16 @@ 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 { - os.Mkdir(m.Conf("logdir"), 0770) log.file = map[string]*os.File{} + os.Mkdir(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")) + + 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 { @@ -90,16 +99,25 @@ var Index = &ctx.Context{Name: "log", Help: "日志中心", }, Configs: map[string]*ctx.Config{ "logdir": &ctx.Config{Name: "logdir", Value: "var/log", Help: ""}, + "logpid": &ctx.Config{Name: "logpid", Value: "var/log/bench.pid", Help: ""}, "output": &ctx.Config{Name: "output", Value: map[string]interface{}{ - "error": map[string]interface{}{"value": map[string]interface{}{"file": "error.log", "meta": []interface{}{"time", "ship"}, "color_begin": "\033[31m", "color_end": "\033[0m"}}, - "trace": map[string]interface{}{"value": map[string]interface{}{"file": "error.log", "meta": []interface{}{"time", "ship"}, "color_begin": "\033[32m", "color_end": "\033[0m"}}, - "debug": map[string]interface{}{"value": map[string]interface{}{"file": "debug.log", "meta": []interface{}{"time", "ship"}}}, + "error": map[string]interface{}{"value": map[string]interface{}{"file": "error.log", "meta": []interface{}{"time", "ship"}, "color_begin": "\033[31m", "color_end": "\033[0m"}}, + "trace": map[string]interface{}{"value": map[string]interface{}{"file": "error.log", "meta": []interface{}{"time", "ship"}, "color_begin": "\033[32m", "color_end": "\033[0m"}}, + "debug": map[string]interface{}{"value": map[string]interface{}{"file": "debug.log", "meta": []interface{}{"time", "ship"}}}, + "search": map[string]interface{}{"value": map[string]interface{}{"file": "debug.log", "meta": []interface{}{"time", "ship"}}}, + "cbs": map[string]interface{}{"value": map[string]interface{}{"file": "debug.log", "meta": []interface{}{"time", "ship"}}}, "bench": map[string]interface{}{"value": map[string]interface{}{"file": "bench.log", "meta": []interface{}{"time", "ship"}}}, "begin": map[string]interface{}{"value": map[string]interface{}{"file": "bench.log", "meta": []interface{}{"time", "ship"}, "color_begin": "\033[31m", "color_end": "\033[0m"}}, "start": map[string]interface{}{"value": map[string]interface{}{"file": "bench.log", "meta": []interface{}{"time", "ship"}, "color_begin": "\033[31m", "color_end": "\033[0m"}}, + "close": map[string]interface{}{"value": map[string]interface{}{"file": "bench.log", "meta": []interface{}{"time", "ship"}, "color_begin": "\033[31m", "color_end": "\033[0m"}}, + "cmd": map[string]interface{}{"value": map[string]interface{}{"file": "bench.log", "meta": []interface{}{"time", "ship"}, "color_begin": "\033[32m", "color_end": "\033[0m"}, "lex": map[string]interface{}{"value": map[string]interface{}{"file": "debug.log", "meta": []interface{}{"time", "ship"}, "color_begin": "\033[32m", "color_end": "\033[0m"}}, + "yac": map[string]interface{}{"value": map[string]interface{}{"file": "debug.log", "meta": []interface{}{"time", "ship"}, "color_begin": "\033[32m", "color_end": "\033[0m"}}, + "cli": map[string]interface{}{ + "cmd": map[string]interface{}{"value": map[string]interface{}{"file": "debug.log", "meta": []interface{}{"time", "ship"}, "color_begin": "\033[31m", "color_end": "\033[0m"}}, + }, }, }, Help: "日志输出配置"}, }, diff --git a/src/contexts/log/log_test.go b/src/contexts/log/log_test.go new file mode 100644 index 00000000..fd0e8c11 --- /dev/null +++ b/src/contexts/log/log_test.go @@ -0,0 +1,19 @@ +package log + +import ( + "contexts/ctx" + "testing" +) + +func TestLog(t *testing.T) { + m := ctx.Pulse.Spawn(Index) + m.Target().Begin(m) + m.Sess("log", m) + m.Log("error", "what %v", 123) + m.Log("debug", "what %v", 123) + m.Log("info", "what %v", 123) + m.Log("cmd", "what %v", 123) + m.Log("begin", "what %v", 123) + m.Log("search", "what %v", 123) + m.Cmd("log", "search", "what %v", 123) +} diff --git a/src/contexts/nfs/nfs.go b/src/contexts/nfs/nfs.go index 297a00df..926a3ffb 100644 --- a/src/contexts/nfs/nfs.go +++ b/src/contexts/nfs/nfs.go @@ -18,9 +18,9 @@ import ( "os/exec" "path" "regexp" + // "runtime" "sort" - "strconv" "strings" "time" "toolkit" @@ -50,31 +50,6 @@ type NFS struct { *ctx.Context } -func open(m *ctx.Message, name string, arg ...int) (string, *os.File, error) { - if !path.IsAbs(name) { - paths := m.Confv("paths").([]interface{}) - for _, v := range paths { - p := path.Join(v.(string), name) - if len(arg) > 0 { - name = p - break - } - if s, e := os.Stat(p); e == nil && !s.IsDir() { - name = p - break - } - } - } - - flag := os.O_RDONLY - if len(arg) > 0 { - flag = arg[0] - } - - m.Log("info", "open %s", name) - f, e := os.OpenFile(name, flag, 0660) - return name, f, e -} func dir(m *ctx.Message, name string, level int, deep bool, dir_type string, trip int, dir_reg *regexp.Regexp, fields []string, format string) { back, e := os.Getwd() m.Assert(e) @@ -167,6 +142,31 @@ func dir(m *ctx.Message, name string, level int, deep bool, dir_type string, tri } } } +func open(m *ctx.Message, name string, arg ...int) (string, *os.File, error) { + if !path.IsAbs(name) { + paths := m.Confv("paths").([]interface{}) + for _, v := range paths { + p := path.Join(v.(string), name) + if len(arg) > 0 { + name = p + break + } + if s, e := os.Stat(p); e == nil && !s.IsDir() { + name = p + break + } + } + } + + flag := os.O_RDONLY + if len(arg) > 0 { + flag = arg[0] + } + + m.Log("info", "open %s", name) + f, e := os.OpenFile(name, flag, 0660) + return name, f, e +} func (nfs *NFS) insert(rest []rune, letters []rune) []rune { n := len(rest) @@ -530,8 +530,9 @@ func (nfs *NFS) Read(p []byte) (n int, err error) { func (nfs *NFS) prompt(arg ...string) string { m := nfs.Context.Message() - target := m.Optionv("ps_target").(*ctx.Context) + target, _ := m.Optionv("ps_target").(*ctx.Context) nfs.out.WriteString(fmt.Sprintf("%d[%s]%s> ", m.Capi("ninput"), time.Now().Format("15:04:05"), target.Name)) + return "" return "> " ps := nfs.Option("prompt") @@ -583,11 +584,8 @@ func (nfs *NFS) Spawn(m *ctx.Message, c *ctx.Context, arg ...string) ctx.Server "size": &ctx.Cache{Name: "size", Value: "0", Help: "size"}, "nread": &ctx.Cache{Name: "nread", Value: "0", Help: "nread"}, "nwrite": &ctx.Cache{Name: "nwrite", Value: "0", Help: "nwrite"}, - "nline": &ctx.Cache{Name: "缓存命令行数", Value: "0", Help: "缓存命令行数"}, - } - c.Configs = map[string]*ctx.Config{ - "history": &ctx.Config{Name: "history", Value: []interface{}{}, Help: "读取记录"}, } + c.Configs = map[string]*ctx.Config{} } else { c.Caches = map[string]*ctx.Cache{ "nsend": &ctx.Cache{Name: "消息发送数量", Value: "0", Help: "消息发送数量"}, @@ -605,7 +603,6 @@ func (nfs *NFS) Spawn(m *ctx.Message, c *ctx.Context, arg ...string) ctx.Server } func (nfs *NFS) Begin(m *ctx.Message, arg ...string) ctx.Server { nfs.Message = m - nfs.width, nfs.height = 1, 1 return nfs } func (nfs *NFS) Start(m *ctx.Message, arg ...string) bool { @@ -700,6 +697,7 @@ func (nfs *NFS) Start(m *ctx.Message, arg ...string) bool { if m.Cap("stream", arg[1]) == "stdio" { nfs.out = m.Optionv("out").(*os.File) + nfs.width, nfs.height = 1, 1 // if !m.Caps("windows", runtime.GOOS == "windows") { // termbox.Init() // defer termbox.Close() @@ -836,10 +834,12 @@ func (nfs *NFS) Close(m *ctx.Message, arg ...string) bool { switch nfs.Context { case m.Target(): if nfs.in != nil { + m.Log("info", "close in %s", m.Cap("stream")) nfs.in.Close() nfs.in = nil } if nfs.out != nil { + m.Log("info", "close out %s", m.Cap("stream")) nfs.out.Close() nfs.out = nil } @@ -946,7 +946,7 @@ var Index = &ctx.Context{Name: "nfs", Help: "存储中心", } return }}, - "git": &ctx.Command{Name: "git", Help: "版本控制", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { + "git": &ctx.Command{Name: "git sum", Help: "版本控制", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { if len(arg) > 0 && arg[0] == "sum" { if out, e := exec.Command("git", "log", "--shortstat", "--pretty=commit: %ad", "--date=format:%Y-%m-%d").CombinedOutput(); m.Assert(e) { for _, v := range strings.Split(string(out), "commit: ") { @@ -1008,29 +1008,23 @@ var Index = &ctx.Context{Name: "nfs", Help: "存储中心", }}, "path": &ctx.Command{Name: "path file", Help: "查找文件路径", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { - for _, v := range m.Confv("paths").([]interface{}) { - p := path.Join(v.(string), arg[0]) + m.Confm("paths", func(index int, value string) bool { + p := path.Join(value, arg[0]) if _, e := os.Stat(p); e == nil { m.Echo(p) - break + return true } - } + return false + }) return }}, "load": &ctx.Command{Name: "load file [buf_size [pos]]", Help: "加载文件, buf_size: 加载大小, pos: 加载位置", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { if p, f, e := open(m, arg[0]); m.Assert(e) { defer f.Close() - pos := 0 - if len(arg) > 2 { - i, e := strconv.Atoi(arg[2]) - m.Assert(e) - pos = i - } - - s, e := strconv.Atoi(m.Confx("buf_size", arg, 1)) - m.Assert(e) - buf := make([]byte, s) + pos := kit.Int(kit.Select("0", arg, 2)) + size := kit.Int(m.Confx("buf_size", arg, 1)) + buf := make([]byte, size) if l, e := f.ReadAt(buf, int64(pos)); e == io.EOF || m.Assert(e) { m.Log("info", "load %s %d %d", p, l, pos) @@ -1043,7 +1037,7 @@ var Index = &ctx.Context{Name: "nfs", Help: "存储中心", if len(arg) == 1 && m.Has("data") { arg = append(arg, m.Option("data")) } - if p, f, e := open(m, arg[0], os.O_WRONLY|os.O_CREATE|os.O_TRUNC); m.Assert(e) { + if p, f, e := open(m, m.Format(arg[0]), os.O_WRONLY|os.O_CREATE|os.O_TRUNC); m.Assert(e) { defer f.Close() m.Append("directory", p) m.Echo(p) @@ -1056,67 +1050,24 @@ var Index = &ctx.Context{Name: "nfs", Help: "存储中心", } return }}, - "export": &ctx.Command{Name: "export filename", Help: "导出数据", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { - name := time.Now().Format(arg[0]) - _, f, e := open(m, name, os.O_WRONLY|os.O_CREATE|os.O_TRUNC) - m.Assert(e) - defer f.Close() - - switch { - case strings.HasSuffix(arg[0], ".json") && len(m.Meta["append"]) > 0: - data := []interface{}{} - - nrow := len(m.Meta[m.Meta["append"][0]]) - for i := 0; i < nrow; i++ { - line := map[string]interface{}{} - for _, k := range m.Meta["append"] { - line[k] = m.Meta[k][i] - } - data = append(data, line) - } - en := json.NewEncoder(f) - en.SetIndent("", " ") - en.Encode(data) - - case strings.HasSuffix(arg[0], ".csv") && len(m.Meta["append"]) > 0: - w := csv.NewWriter(f) - - line := []string{} - for _, v := range m.Meta["append"] { - line = append(line, v) - } - w.Write(line) - - nrow := len(m.Meta[m.Meta["append"][0]]) - for i := 0; i < nrow; i++ { - line := []string{} - for _, k := range m.Meta["append"] { - line = append(line, m.Meta[k][i]) - } - w.Write(line) - } - w.Flush() - default: - for _, v := range m.Meta["result"] { - f.WriteString(v) - } - } - m.Set("append").Set("result").Add("append", "directory", name).Echo(name) - return - }}, "import": &ctx.Command{Name: "import filename [index]", Help: "导入数据", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { - _, f, e := open(m, arg[0]) + p, f, e := open(m, arg[0]) m.Assert(e) defer f.Close() + s, e := f.Stat() + m.Option("filepath", p) + m.Option("filename", s.Name()) + m.Option("filesize", s.Size()) + m.Option("filetime", s.ModTime().Format(m.Conf("time_format"))) + switch { case strings.HasSuffix(arg[0], ".json"): var data interface{} de := json.NewDecoder(f) de.Decode(&data) - msg := m.Spawn().Put("option", "data", data).Cmd("trans", "data", arg[1:]) - m.Copy(msg, "append").Copy(msg, "result") + m.Put("option", "filedata", data).Cmdy("ctx.trans", "filedata", arg[1:]).CopyTo(m) case strings.HasSuffix(arg[0], ".csv"): r := csv.NewReader(f) @@ -1130,9 +1081,96 @@ var Index = &ctx.Context{Name: "nfs", Help: "存储中心", } } m.Table() + default: + b, e := ioutil.ReadAll(f) + m.Assert(e) + m.Echo(string(b)) } return }}, + "export": &ctx.Command{Name: "export filename", Help: "导出数据", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { + tp := false + if len(arg) > 0 && arg[0] == "time" { + tp, arg = true, arg[1:] + } + + p, f, e := open(m, kit.Select(arg[0], m.Format(arg[0]), tp), os.O_WRONLY|os.O_CREATE|os.O_TRUNC) + m.Assert(e) + defer f.Close() + + m.Option("hi", "hello world") + m.Option("he", "hello", "world") + + m.Append("he", "hello", "world") + m.Append("hi", "nice", "job") + + data := m.Optionv(kit.Select("data", arg, 1)) + if len(arg) > 0 && arg[0] == "all" { + data, arg = m.Meta, arg[1:] + } + + switch { + case strings.HasSuffix(arg[0], ".json"): + if data == nil && len(m.Meta["append"]) > 0 { + lines := []interface{}{} + nrow := len(m.Meta[m.Meta["append"][0]]) + for i := 0; i < nrow; i++ { + line := map[string]interface{}{} + for _, k := range m.Meta["append"] { + line[k] = m.Meta[k][i] + } + + lines = append(lines, line) + data = lines + } + } + + en := json.NewEncoder(f) + en.SetIndent("", " ") + en.Encode(data) + case strings.HasSuffix(arg[0], ".csv"): + fields := m.Meta["append"] + if m.Options("fields") { + fields = m.Meta["fields"] + } + + if data == nil && len(m.Meta["append"]) > 0 { + lines := []interface{}{} + nrow := len(m.Meta[m.Meta["append"][0]]) + for i := 0; i < nrow; i++ { + line := []string{} + for _, k := range fields { + line = append(line, m.Meta[k][i]) + } + lines = append(lines, line) + data = lines + } + } + + if data, ok := data.([]interface{}); ok { + w := csv.NewWriter(f) + w.Write(fields) + for _, v := range data { + w.Write(kit.Trans(v)) + } + w.Flush() + } + case strings.HasSuffix(arg[0], ".png"): + if data == nil { + data = kit.Format(arg[1:]) + } + + qr, e := qrcode.New(kit.Format(data), qrcode.Medium) + m.Assert(e) + m.Assert(qr.Write(256, f)) + default: + f.WriteString(kit.Format(m.Meta["result"])) + } + + m.Set("append").Add("append", "directory", p) + m.Set("result").Echo(p) + return + }}, "open": &ctx.Command{Name: "open file", Help: "打开文件, file: 文件名", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { if m.Has("io") { @@ -1144,7 +1182,8 @@ var Index = &ctx.Context{Name: "nfs", Help: "存储中心", } m.Start(fmt.Sprintf("file%d", m.Capi("nfile")), fmt.Sprintf("file %s", arg[0]), "open", arg[0]) - m.Echo(arg[0]) + m.Append("ps_target1", m.Cap("module")) + m.Echo(m.Cap("module")) return }}, "read": &ctx.Command{Name: "read [buf_size [pos]]", Help: "读取文件, buf_size: 读取大小, pos: 读取位置", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { @@ -1213,6 +1252,23 @@ var Index = &ctx.Context{Name: "nfs", Help: "存储中心", } return }}, + "exec": &ctx.Command{Name: "exec cmd", Help: "", 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.out != nil { + nfs.prompt() + for _, v := range arg { + nfs.out.WriteString(v) + } + nfs.out.WriteString("\n") + + msg := m.Find("cli.shell1").Cmd("source", arg) + for _, v := range msg.Meta["result"] { + nfs.out.WriteString(v) + m.Echo(v) + } + nfs.out.WriteString("\n") + } + 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) { if _, ok := m.Target().Server.(*NFS); m.Assert(ok) { //{{{ @@ -1253,88 +1309,6 @@ var Index = &ctx.Context{Name: "nfs", Help: "存储中心", } return }}, - - "exec": &ctx.Command{Name: "exec cmd", Help: "", 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.out != nil { - nfs.prompt() - for _, v := range arg { - nfs.out.WriteString(v) - } - nfs.out.WriteString("\n") - - msg := m.Find("cli.shell1").Cmd("source", arg) - for _, v := range msg.Meta["result"] { - nfs.out.WriteString(v) - m.Echo(v) - } - nfs.out.WriteString("\n") - } - return - }}, - "print": &ctx.Command{Name: "print file string...", Help: "输出文件, file: 输出的文件, string: 输出的内容", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { - if p, f, e := open(m, arg[0], os.O_WRONLY|os.O_CREATE|os.O_APPEND); m.Assert(e) { - defer f.Close() - - for _, v := range arg[1:] { - n, e := fmt.Fprint(f, v) - m.Assert(e) - m.Log("info", "print %s %d", p, n) - } - } - return - }}, - "json": &ctx.Command{Name: "json [key value]...", Help: "生成格式化内容, key: 参数名, value: 参数值", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { - if len(arg) == 1 { - var data interface{} - json.Unmarshal([]byte(arg[0]), &data) - - buf, e := json.MarshalIndent(data, "", " ") - m.Assert(e) - m.Echo(string(buf)) - return e - } - - if len(arg) > 1 && arg[0] == "file" { - var data interface{} - f, e := os.Open(arg[1]) - m.Assert(e) - d := json.NewDecoder(f) - d.Decode(&data) - - buf, e := json.MarshalIndent(data, "", " ") - m.Assert(e) - m.Echo(string(buf)) - return e - } - - data := map[string]interface{}{} - for _, k := range m.Meta["option"] { - if v, ok := m.Data[k]; ok { - data[k] = v - continue - } - data[k] = m.Meta[k] - } - - for i := 1; i < len(arg)-1; i += 2 { - data[arg[i]] = arg[i+1] - } - - buf, e := json.Marshal(data) - m.Assert(e) - m.Echo(string(buf)) - - return - }}, - "genqr": &ctx.Command{Name: "genqr [qr_size size] filename string...", Help: "生成二维码图片, qr_size: 图片大小, filename: 文件名, string: 输出内容", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { - if size, e := strconv.Atoi(m.Confx("qr_size")); m.Assert(e) { - p := path.Join(m.Confv("paths", 0).(string), arg[0]) - qrcode.WriteFile(strings.Join(arg[1:], ""), qrcode.Medium, size, p) - m.Log("info", "genqr %s", p) - m.Append("directory", p) - } - return - }}, }, } diff --git a/src/toolkit/kit.go b/src/toolkit/kit.go index 42737632..7cb5560c 100644 --- a/src/toolkit/kit.go +++ b/src/toolkit/kit.go @@ -286,6 +286,7 @@ func Select(value string, args ...interface{}) string { if b && arg != "" { return arg } + return value } } if arg != "" { @@ -458,6 +459,27 @@ func Hash(arg ...interface{}) (string, []string) { h := md5.Sum([]byte(strings.Join(meta, ""))) return hex.EncodeToString(h[:]), meta } +func FileName(name string, meta ...string) string { + result, app := strings.Split(name, "."), "" + if len(result) > 1 { + app, result = result[len(result)-1], result[:len(result)-1] + } + + for _, v := range meta { + switch v { + case "year": + result = append(result, "_", time.Now().Format("2006")) + case "date": + result = append(result, "_", time.Now().Format("0102")) + case "time": + result = append(result, "_", time.Now().Format("2006_0102_1504")) + } + } + if app != "" { + result = append(result, ".", app) + } + return strings.Join(result, "") +} func Action(cmd string, arg ...interface{}) string { switch cmd {