forked from x/icebergs
opt mdb
This commit is contained in:
parent
46759d6795
commit
b383b945fd
@ -120,8 +120,8 @@ var Index = &ice.Context{Name: "log", Help: "日志模块",
|
|||||||
// 日志文件
|
// 日志文件
|
||||||
if f, p, e := kit.Create(kit.Format(value["path"])); m.Assert(e) {
|
if f, p, e := kit.Create(kit.Format(value["path"])); m.Assert(e) {
|
||||||
m.Cap(ice.CTX_STREAM, path.Base(p))
|
m.Cap(ice.CTX_STREAM, path.Base(p))
|
||||||
m.Log("create", "%s: %s", key, p)
|
|
||||||
value["file"] = bufio.NewWriter(f)
|
value["file"] = bufio.NewWriter(f)
|
||||||
|
m.Log_CREATE(kit.MDB_FILE, p)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
166
base/mdb/mdb.go
166
base/mdb/mdb.go
@ -4,17 +4,18 @@ import (
|
|||||||
"github.com/shylinux/icebergs"
|
"github.com/shylinux/icebergs"
|
||||||
"github.com/shylinux/icebergs/base/web"
|
"github.com/shylinux/icebergs/base/web"
|
||||||
"github.com/shylinux/toolkits"
|
"github.com/shylinux/toolkits"
|
||||||
|
"github.com/shylinux/toolkits/task"
|
||||||
|
|
||||||
"encoding/csv"
|
"encoding/csv"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"os"
|
"os"
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func _list_import(m *ice.Message, prefix, key, file string) {
|
func _list_import(m *ice.Message, prefix, key, file string) {
|
||||||
f, e := os.Open(file)
|
f, e := os.Open(file)
|
||||||
m.Assert(e)
|
m.Assert(e)
|
||||||
|
defer m.Cmdy(web.STORY, web.CATCH, CSV, file)
|
||||||
defer f.Close()
|
defer f.Close()
|
||||||
|
|
||||||
r := csv.NewReader(f)
|
r := csv.NewReader(f)
|
||||||
@ -43,10 +44,10 @@ func _list_import(m *ice.Message, prefix, key, file string) {
|
|||||||
m.Log_IMPORT(kit.MDB_KEY, kit.Keys(prefix, key), kit.MDB_COUNT, count)
|
m.Log_IMPORT(kit.MDB_KEY, kit.Keys(prefix, key), kit.MDB_COUNT, count)
|
||||||
}
|
}
|
||||||
func _list_export(m *ice.Message, prefix, key, file string) {
|
func _list_export(m *ice.Message, prefix, key, file string) {
|
||||||
f, p, e := kit.Create(kit.Keys(file, "csv"))
|
f, p, e := kit.Create(kit.Keys(file, CSV))
|
||||||
m.Assert(e)
|
m.Assert(e)
|
||||||
|
defer m.Cmdy(web.STORY, web.CATCH, CSV, p)
|
||||||
defer f.Close()
|
defer f.Close()
|
||||||
defer m.Cmdy(web.STORY, "catch", "csv", p)
|
|
||||||
|
|
||||||
w := csv.NewWriter(f)
|
w := csv.NewWriter(f)
|
||||||
defer w.Flush()
|
defer w.Flush()
|
||||||
@ -73,54 +74,101 @@ func _list_export(m *ice.Message, prefix, key, file string) {
|
|||||||
})
|
})
|
||||||
m.Log_EXPORT(kit.MDB_FILE, p, kit.MDB_COUNT, count)
|
m.Log_EXPORT(kit.MDB_FILE, p, kit.MDB_COUNT, count)
|
||||||
}
|
}
|
||||||
|
func _list_select(m *ice.Message, prefix, key, limit, offend, field, value string) {
|
||||||
|
m.Option("cache.limit", limit)
|
||||||
|
m.Option("cache.offend", offend)
|
||||||
|
m.Grows(prefix, key, field, value, func(index int, value map[string]interface{}) {
|
||||||
|
m.Push("", value)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
func _list_search(m *ice.Message, prefix, key, field, value string) {
|
||||||
|
list := []interface{}{}
|
||||||
|
files := map[string]bool{}
|
||||||
|
m.Richs(prefix, key, kit.MDB_FOREACH, func(key string, value map[string]interface{}) {
|
||||||
|
kit.Fetch(kit.Value(value, "meta.record"), func(index int, value map[string]interface{}) {
|
||||||
|
file := value["file"].(string)
|
||||||
|
if _, ok := files[file]; ok {
|
||||||
|
list = append(list, file)
|
||||||
|
} else {
|
||||||
|
files[file] = true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
defer m.Cost("search")
|
||||||
|
|
||||||
|
task.Sync(list, func(task *task.Task, lock *task.Lock) error {
|
||||||
|
kit.CSV(kit.Format(task.Arg), 100000, func(index int, line map[string]string, head []string) {
|
||||||
|
if line[field] != value {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
defer lock.WLock()()
|
||||||
|
m.Push("", line)
|
||||||
|
})
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func _hash_search(m *ice.Message, prefix, key, field, value string) {
|
||||||
|
m.Richs(prefix, key, kit.MDB_FOREACH, func(key string, val map[string]interface{}) {
|
||||||
|
if field != "" && value != val[field] {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
m.Push(key, value)
|
||||||
|
})
|
||||||
|
}
|
||||||
func _hash_import(m *ice.Message, prefix, key, file string) {
|
func _hash_import(m *ice.Message, prefix, key, file string) {
|
||||||
f, e := os.Open(file)
|
f, e := os.Open(file)
|
||||||
m.Assert(e)
|
m.Assert(e)
|
||||||
|
defer m.Cmdy(web.STORY, web.CATCH, JSON, file)
|
||||||
defer f.Close()
|
defer f.Close()
|
||||||
|
|
||||||
defer m.Log_IMPORT(kit.MDB_FILE, file)
|
list := map[string]interface{}{}
|
||||||
|
|
||||||
data := map[string]interface{}{}
|
|
||||||
de := json.NewDecoder(f)
|
de := json.NewDecoder(f)
|
||||||
de.Decode(&data)
|
de.Decode(&list)
|
||||||
|
|
||||||
for k, v := range data {
|
count := 0
|
||||||
m.Log_MODIFY(kit.MDB_KEY, kit.Keys(prefix, key, kit.MDB_HASH), "k", k, "v", v)
|
for _, data := range list {
|
||||||
m.Conf(prefix, kit.Keys(key, k), v)
|
// 导入数据
|
||||||
|
m.Rich(prefix, key, data)
|
||||||
|
count++
|
||||||
}
|
}
|
||||||
|
m.Log_IMPORT(kit.MDB_KEY, kit.Keys(prefix, key), kit.MDB_COUNT, count)
|
||||||
}
|
}
|
||||||
func _hash_export(m *ice.Message, prefix, key, file string) {
|
func _hash_export(m *ice.Message, prefix, key, file string) {
|
||||||
f, p, e := kit.Create(kit.Keys(file, "json"))
|
f, p, e := kit.Create(kit.Keys(file, JSON))
|
||||||
m.Assert(e)
|
m.Assert(e)
|
||||||
|
defer m.Cmdy(web.STORY, web.CATCH, JSON, p)
|
||||||
defer f.Close()
|
defer f.Close()
|
||||||
defer m.Cmdy(web.STORY, "catch", "json", p)
|
|
||||||
|
|
||||||
en := json.NewEncoder(f)
|
en := json.NewEncoder(f)
|
||||||
en.SetIndent("", " ")
|
en.SetIndent("", " ")
|
||||||
en.Encode(m.Confv(prefix, kit.Keys(key, kit.MDB_HASH)))
|
en.Encode(m.Confv(prefix, kit.Keys(key, HASH)))
|
||||||
m.Log_EXPORT(kit.MDB_FILE, p)
|
m.Log_EXPORT(kit.MDB_FILE, p)
|
||||||
}
|
}
|
||||||
func _dict_import(m *ice.Message, prefix, key, file string) {
|
func _dict_import(m *ice.Message, prefix, key, file string) {
|
||||||
f, e := os.Open(file)
|
f, e := os.Open(file)
|
||||||
m.Assert(e)
|
m.Assert(e)
|
||||||
|
m.Cmdy(web.STORY, web.CATCH, JSON, file)
|
||||||
defer f.Close()
|
defer f.Close()
|
||||||
|
|
||||||
defer m.Log_IMPORT(kit.MDB_FILE, file)
|
|
||||||
|
|
||||||
data := map[string]interface{}{}
|
data := map[string]interface{}{}
|
||||||
de := json.NewDecoder(f)
|
de := json.NewDecoder(f)
|
||||||
de.Decode(&data)
|
de.Decode(&data)
|
||||||
|
|
||||||
|
count := 0
|
||||||
for k, v := range data {
|
for k, v := range data {
|
||||||
m.Log_MODIFY(kit.MDB_KEY, kit.Keys(prefix, key), "k", k, "v", v)
|
m.Log_MODIFY(kit.MDB_KEY, kit.Keys(prefix, key), "k", k, "v", v)
|
||||||
m.Conf(prefix, kit.Keys(key, k), v)
|
m.Conf(prefix, kit.Keys(key, k), v)
|
||||||
|
count++
|
||||||
}
|
}
|
||||||
|
m.Log_EXPORT(kit.MDB_FILE, file, kit.MDB_COUNT, count)
|
||||||
}
|
}
|
||||||
func _dict_export(m *ice.Message, prefix, key, file string) {
|
func _dict_export(m *ice.Message, prefix, key, file string) {
|
||||||
f, p, e := kit.Create(kit.Keys(file, "json"))
|
f, p, e := kit.Create(kit.Keys(file, JSON))
|
||||||
m.Assert(e)
|
m.Assert(e)
|
||||||
|
defer m.Cmdy(web.STORY, web.CATCH, JSON, p)
|
||||||
defer f.Close()
|
defer f.Close()
|
||||||
defer m.Cmdy(web.STORY, "catch", "json", p)
|
|
||||||
|
|
||||||
en := json.NewEncoder(f)
|
en := json.NewEncoder(f)
|
||||||
en.SetIndent("", " ")
|
en.SetIndent("", " ")
|
||||||
@ -128,72 +176,66 @@ func _dict_export(m *ice.Message, prefix, key, file string) {
|
|||||||
m.Log_EXPORT(kit.MDB_FILE, p)
|
m.Log_EXPORT(kit.MDB_FILE, p)
|
||||||
}
|
}
|
||||||
|
|
||||||
const IMPORT = "import"
|
const (
|
||||||
const EXPORT = "export"
|
CSV = "csv"
|
||||||
|
JSON = "json"
|
||||||
|
)
|
||||||
|
const (
|
||||||
|
DICT = "dict"
|
||||||
|
META = "meta"
|
||||||
|
HASH = "hash"
|
||||||
|
LIST = "list"
|
||||||
|
)
|
||||||
|
const (
|
||||||
|
IMPORT = "import"
|
||||||
|
EXPORT = "export"
|
||||||
|
SELECT = "select"
|
||||||
|
SEARCH = "search"
|
||||||
|
)
|
||||||
|
|
||||||
var Index = &ice.Context{Name: "mdb", Help: "数据模块",
|
var Index = &ice.Context{Name: "mdb", Help: "数据模块",
|
||||||
Commands: map[string]*ice.Command{
|
Commands: map[string]*ice.Command{
|
||||||
ice.ICE_INIT: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {}},
|
ice.ICE_INIT: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {}},
|
||||||
ice.ICE_EXIT: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {}},
|
ice.ICE_EXIT: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {}},
|
||||||
kit.MDB_IMPORT: {Name: "import conf key type file", Help: "导入数据", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
|
|
||||||
|
IMPORT: {Name: "import conf key type file", Help: "导入数据", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
|
||||||
switch arg[2] {
|
switch arg[2] {
|
||||||
case kit.MDB_LIST:
|
case LIST:
|
||||||
_list_import(m, arg[0], arg[1], arg[3])
|
_list_import(m, arg[0], arg[1], arg[3])
|
||||||
case kit.MDB_HASH:
|
case HASH:
|
||||||
_hash_import(m, arg[0], arg[1], arg[3])
|
_hash_import(m, arg[0], arg[1], arg[3])
|
||||||
case kit.MDB_DICT:
|
case DICT:
|
||||||
_dict_import(m, arg[0], arg[1], arg[3])
|
_dict_import(m, arg[0], arg[1], arg[3])
|
||||||
}
|
}
|
||||||
}},
|
}},
|
||||||
kit.MDB_EXPORT: {Name: "export conf key type [name]", Help: "导出数据", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
|
EXPORT: {Name: "export conf key type [name]", Help: "导出数据", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
|
||||||
switch file := kit.Select(kit.Select(arg[0], arg[0]+":"+arg[1], arg[1] != ""), arg, 3); arg[2] {
|
switch file := kit.Select(kit.Select(arg[0], arg[0]+":"+arg[1], arg[1] != ""), arg, 3); arg[2] {
|
||||||
case kit.MDB_LIST:
|
case LIST:
|
||||||
_list_export(m, arg[0], arg[1], file)
|
_list_export(m, arg[0], arg[1], file)
|
||||||
case kit.MDB_HASH:
|
case HASH:
|
||||||
_hash_export(m, arg[0], arg[1], file)
|
_hash_export(m, arg[0], arg[1], file)
|
||||||
case kit.MDB_DICT:
|
case DICT:
|
||||||
_dict_export(m, arg[0], arg[1], file)
|
_dict_export(m, arg[0], arg[1], file)
|
||||||
}
|
}
|
||||||
}},
|
}},
|
||||||
|
|
||||||
"update": {Name: "update config table index key value", Help: "修改数据", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
|
SELECT: {Name: "select conf key type [limit [offend [key value]]]", Help: "数据查询", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
|
||||||
meta := m.Confm(arg[0], arg[1]+".meta")
|
|
||||||
index := kit.Int(arg[2]) - kit.Int(meta["offset"]) - 1
|
|
||||||
|
|
||||||
data := m.Confm(arg[0], arg[1]+".list."+kit.Format(index))
|
|
||||||
for i := 3; i < len(arg)-1; i += 2 {
|
|
||||||
kit.Value(data, arg[i], arg[i+1])
|
|
||||||
}
|
|
||||||
}},
|
|
||||||
"select": {Name: "select config table index offend limit match value", Help: "修改数据", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
|
|
||||||
if len(arg) == 3 {
|
|
||||||
meta := m.Confm(arg[0], arg[1]+".meta")
|
|
||||||
index := kit.Int(arg[2]) - kit.Int(meta["offset"]) - 1
|
|
||||||
|
|
||||||
data := m.Confm(arg[0], arg[1]+".list."+kit.Format(index))
|
|
||||||
m.Push(arg[2], data)
|
|
||||||
} else {
|
|
||||||
m.Option("cache.offend", kit.Select("0", arg, 3))
|
|
||||||
m.Option("cache.limit", kit.Select("10", arg, 4))
|
|
||||||
fields := strings.Split(arg[7], " ")
|
|
||||||
m.Grows(arg[0], arg[1], kit.Select("", arg, 5), kit.Select("", arg, 6), func(index int, value map[string]interface{}) {
|
|
||||||
m.Push("id", value, fields)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}},
|
|
||||||
|
|
||||||
ice.MDB_DELETE: {Name: "delete conf key type", Help: "删除", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
|
|
||||||
switch arg[2] {
|
switch arg[2] {
|
||||||
case kit.MDB_DICT:
|
case LIST:
|
||||||
m.Log(ice.LOG_DELETE, "%s: %s", arg[1], m.Conf(arg[0], arg[1]))
|
_list_select(m, arg[0], arg[1], kit.Select("10", arg, 3), kit.Select("0", arg, 4), kit.Select("", arg, 5), kit.Select("", arg, 6))
|
||||||
m.Echo("%s", m.Conf(arg[0], arg[1]))
|
}
|
||||||
m.Conf(arg[0], arg[1], "")
|
}},
|
||||||
case kit.MDB_META:
|
SEARCH: {Name: "search conf key type key value", Help: "数据查询", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
|
||||||
case kit.MDB_LIST:
|
switch arg[2] {
|
||||||
case kit.MDB_HASH:
|
case LIST:
|
||||||
|
_list_search(m, arg[0], arg[1], arg[3], arg[4])
|
||||||
|
case HASH:
|
||||||
|
_hash_search(m, arg[0], arg[1], arg[3], arg[4])
|
||||||
}
|
}
|
||||||
}},
|
}},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() { ice.Index.Register(Index, nil, IMPORT, EXPORT) }
|
func init() {
|
||||||
|
ice.Index.Register(Index, nil, IMPORT, EXPORT, SELECT, SEARCH)
|
||||||
|
}
|
||||||
|
@ -2,6 +2,8 @@ package nfs
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
ice "github.com/shylinux/icebergs"
|
ice "github.com/shylinux/icebergs"
|
||||||
|
"github.com/shylinux/icebergs/base/cli"
|
||||||
|
"github.com/shylinux/icebergs/base/web"
|
||||||
kit "github.com/shylinux/toolkits"
|
kit "github.com/shylinux/toolkits"
|
||||||
|
|
||||||
"bufio"
|
"bufio"
|
||||||
@ -18,8 +20,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
FILE = "file"
|
FILE = "file"
|
||||||
TRASH = "trash"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func _file_list(m *ice.Message, root string, name string, level int, deep bool, dir_type string, dir_reg *regexp.Regexp, fields []string) {
|
func _file_list(m *ice.Message, root string, name string, level int, deep bool, dir_type string, dir_reg *regexp.Regexp, fields []string) {
|
||||||
@ -141,12 +142,12 @@ func _file_list(m *ice.Message, root string, name string, level int, deep bool,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
func _file_show(m *ice.Message, name string) {
|
func _file_show(m *ice.Message, name string) {
|
||||||
if f, e := os.OpenFile(name, os.O_RDONLY, 0777); m.Assert(e) {
|
if f, e := os.OpenFile(name, os.O_RDONLY, 0640); m.Assert(e) {
|
||||||
defer f.Close()
|
defer f.Close()
|
||||||
if s, e := f.Stat(); m.Assert(e) {
|
if s, e := f.Stat(); m.Assert(e) {
|
||||||
buf := make([]byte, s.Size())
|
buf := make([]byte, s.Size())
|
||||||
if n, e := f.Read(buf); m.Assert(e) {
|
if n, e := f.Read(buf); m.Assert(e) {
|
||||||
m.Log_IMPORT("file", name, "size", n)
|
m.Log_IMPORT(kit.MDB_FILE, name, kit.MDB_SIZE, n)
|
||||||
m.Echo(string(buf[:n]))
|
m.Echo(string(buf[:n]))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -157,7 +158,7 @@ func _file_save(m *ice.Message, name string, text ...string) {
|
|||||||
defer f.Close()
|
defer f.Close()
|
||||||
for _, v := range text {
|
for _, v := range text {
|
||||||
if n, e := f.WriteString(v); m.Assert(e) {
|
if n, e := f.WriteString(v); m.Assert(e) {
|
||||||
m.Log_EXPORT("file", p, "size", n)
|
m.Log_IMPORT(kit.MDB_FILE, p, kit.MDB_SIZE, n)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
m.Echo(p)
|
m.Echo(p)
|
||||||
@ -170,7 +171,7 @@ func _file_copy(m *ice.Message, name string, from ...string) {
|
|||||||
if s, e := os.Open(v); !m.Warn(e != nil, "%s", e) {
|
if s, e := os.Open(v); !m.Warn(e != nil, "%s", e) {
|
||||||
defer s.Close()
|
defer s.Close()
|
||||||
if n, e := io.Copy(f, s); !m.Warn(e != nil, "%s", e) {
|
if n, e := io.Copy(f, s); !m.Warn(e != nil, "%s", e) {
|
||||||
m.Log_IMPORT("file", p, "size", n)
|
m.Log_IMPORT(kit.MDB_FILE, p, kit.MDB_SIZE, n)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -178,14 +179,14 @@ func _file_copy(m *ice.Message, name string, from ...string) {
|
|||||||
}
|
}
|
||||||
func _file_link(m *ice.Message, name string, from string) {
|
func _file_link(m *ice.Message, name string, from string) {
|
||||||
m.Cmd("nfs.trash", name)
|
m.Cmd("nfs.trash", name)
|
||||||
os.MkdirAll(path.Dir(name), 0777)
|
os.MkdirAll(path.Dir(name), 0760)
|
||||||
os.Link(from, name)
|
os.Link(from, name)
|
||||||
}
|
}
|
||||||
func _file_trash(m *ice.Message, name string, from ...string) {
|
func _file_trash(m *ice.Message, name string, from ...string) {
|
||||||
if s, e := os.Stat(name); e == nil {
|
if s, e := os.Stat(name); e == nil {
|
||||||
if s.IsDir() {
|
if s.IsDir() {
|
||||||
name := path.Base(name) + ".tar.gz"
|
name := path.Base(name) + ".tar.gz"
|
||||||
m.Cmd(ice.CLI_SYSTEM, "tar", "zcf", name, name)
|
m.Cmd(cli.SYSTEM, "tar", "zcf", name, name)
|
||||||
}
|
}
|
||||||
|
|
||||||
if f, e := os.Open(name); m.Assert(e) {
|
if f, e := os.Open(name); m.Assert(e) {
|
||||||
@ -196,36 +197,41 @@ func _file_trash(m *ice.Message, name string, from ...string) {
|
|||||||
os.MkdirAll(path.Dir(p), 0777)
|
os.MkdirAll(path.Dir(p), 0777)
|
||||||
os.Rename(name, p)
|
os.Rename(name, p)
|
||||||
|
|
||||||
m.Cmd(ice.WEB_FAVOR, "trash", "bin", name, p)
|
m.Cmd(web.FAVOR, "trash", "bin", name, p)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func FileSave(m *ice.Message, file string, text ...string) {
|
const (
|
||||||
_file_save(m, file, text...)
|
DIR = "dir"
|
||||||
}
|
CAT = "cat"
|
||||||
|
SAVE = "save"
|
||||||
|
COPY = "copy"
|
||||||
|
LINK = "link"
|
||||||
|
TRASH = "trash"
|
||||||
|
)
|
||||||
|
|
||||||
var Index = &ice.Context{Name: "nfs", Help: "存储模块",
|
var Index = &ice.Context{Name: "nfs", Help: "存储模块",
|
||||||
Configs: map[string]*ice.Config{
|
Configs: map[string]*ice.Config{
|
||||||
TRASH: {Name: "trash", Help: "删除", Value: kit.Data("path", "var/trash")},
|
TRASH: {Name: "trash", Help: "删除", Value: kit.Data("path", "var/trash")},
|
||||||
},
|
},
|
||||||
Commands: map[string]*ice.Command{
|
Commands: map[string]*ice.Command{
|
||||||
"dir": {Name: "dir path field...", Help: "目录", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
|
DIR: {Name: "dir path field...", Help: "目录", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
|
||||||
rg, _ := regexp.Compile(m.Option("dir_reg"))
|
rg, _ := regexp.Compile(m.Option("dir_reg"))
|
||||||
_file_list(m, kit.Select("./", m.Option("dir_root")), kit.Select("", arg, 0),
|
_file_list(m, kit.Select("./", m.Option("dir_root")), kit.Select("", arg, 0),
|
||||||
0, m.Options("dir_deep"), kit.Select("both", m.Option("dir_type")), rg,
|
0, m.Options("dir_deep"), kit.Select("both", m.Option("dir_type")), rg,
|
||||||
strings.Split(kit.Select("time size line path", strings.Join(arg[1:], " ")), " "))
|
strings.Split(kit.Select("time size line path", strings.Join(arg[1:], " ")), " "))
|
||||||
}},
|
}},
|
||||||
"cat": {Name: "cat file", Help: "查看", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
|
CAT: {Name: "cat file", Help: "查看", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
|
||||||
_file_show(m, arg[0])
|
_file_show(m, arg[0])
|
||||||
}},
|
}},
|
||||||
"save": {Name: "save file text...", Help: "保存", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
|
SAVE: {Name: "save file text...", Help: "保存", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
|
||||||
_file_save(m, arg[0], arg[1:]...)
|
_file_save(m, arg[0], arg[1:]...)
|
||||||
}},
|
}},
|
||||||
"copy": {Name: "copy file from...", Help: "复制", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
|
COPY: {Name: "copy file from...", Help: "复制", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
|
||||||
_file_copy(m, arg[0], arg[1:]...)
|
_file_copy(m, arg[0], arg[1:]...)
|
||||||
}},
|
}},
|
||||||
"link": {Name: "link file from", Help: "链接", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
|
LINK: {Name: "link file from", Help: "链接", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
|
||||||
_file_link(m, arg[0], arg[1])
|
_file_link(m, arg[0], arg[1])
|
||||||
}},
|
}},
|
||||||
|
|
||||||
|
454
base/ssh/ssh.go
454
base/ssh/ssh.go
@ -3,6 +3,8 @@ package ssh
|
|||||||
import (
|
import (
|
||||||
"github.com/shylinux/icebergs"
|
"github.com/shylinux/icebergs"
|
||||||
"github.com/shylinux/icebergs/base/aaa"
|
"github.com/shylinux/icebergs/base/aaa"
|
||||||
|
"github.com/shylinux/icebergs/base/cli"
|
||||||
|
"github.com/shylinux/icebergs/base/web"
|
||||||
"github.com/shylinux/toolkits"
|
"github.com/shylinux/toolkits"
|
||||||
|
|
||||||
"bufio"
|
"bufio"
|
||||||
@ -17,15 +19,20 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type Frame struct {
|
type Frame struct {
|
||||||
in io.ReadCloser
|
source string
|
||||||
out io.Writer
|
|
||||||
|
|
||||||
target *ice.Context
|
target *ice.Context
|
||||||
exit bool
|
stdout io.Writer
|
||||||
|
|
||||||
|
count int
|
||||||
|
ps1 []string
|
||||||
|
ps2 []string
|
||||||
|
|
||||||
|
exit bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func Render(msg *ice.Message, cmd string, args ...interface{}) {
|
func Render(msg *ice.Message, cmd string, args ...interface{}) {
|
||||||
msg.Log(ice.LOG_EXPORT, "%s: %v", cmd, args)
|
defer func() { msg.Log_EXPORT(kit.MDB_RENDER, cmd, kit.MDB_TEXT, args) }()
|
||||||
|
|
||||||
switch arg := kit.Simple(args...); cmd {
|
switch arg := kit.Simple(args...); cmd {
|
||||||
case ice.RENDER_OUTPUT:
|
case ice.RENDER_OUTPUT:
|
||||||
|
|
||||||
@ -49,6 +56,7 @@ func Render(msg *ice.Message, cmd string, args ...interface{}) {
|
|||||||
if res == "" {
|
if res == "" {
|
||||||
res = msg.Table().Result()
|
res = msg.Table().Result()
|
||||||
}
|
}
|
||||||
|
args = append(args, "length:", len(res))
|
||||||
|
|
||||||
// 输出结果
|
// 输出结果
|
||||||
if fmt.Fprintf(msg.O, res); !strings.HasSuffix(res, "\n") {
|
if fmt.Fprintf(msg.O, res); !strings.HasSuffix(res, "\n") {
|
||||||
@ -58,60 +66,125 @@ func Render(msg *ice.Message, cmd string, args ...interface{}) {
|
|||||||
msg.Append(ice.MSG_OUTPUT, ice.RENDER_OUTPUT)
|
msg.Append(ice.MSG_OUTPUT, ice.RENDER_OUTPUT)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *Frame) prompt(m *ice.Message) *Frame {
|
func (f *Frame) history(m *ice.Message, line string) string {
|
||||||
if f.out == os.Stdout {
|
favor := m.Conf(SOURCE, kit.Keys(kit.MDB_META, web.FAVOR))
|
||||||
fmt.Fprintf(f.out, "\r")
|
if strings.HasPrefix(strings.TrimSpace(line), "!!") {
|
||||||
for _, v := range kit.Simple(m.Optionv(ice.MSG_PROMPT)) {
|
if len(line) == 2 {
|
||||||
switch v {
|
line = m.Cmd(web.FAVOR, favor).Append(kit.MDB_TEXT)
|
||||||
case "count":
|
|
||||||
fmt.Fprintf(f.out, "%d", kit.Int(m.Conf("history", "meta.count"))+1)
|
|
||||||
case "time":
|
|
||||||
fmt.Fprintf(f.out, time.Now().Format("15:04:05"))
|
|
||||||
case "target":
|
|
||||||
fmt.Fprintf(f.out, f.target.Name)
|
|
||||||
default:
|
|
||||||
fmt.Fprintf(f.out, v)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
} else if strings.HasPrefix(strings.TrimSpace(line), "!") {
|
||||||
|
if len(line) == 1 {
|
||||||
|
// 历史记录
|
||||||
|
msg := m.Cmd(web.FAVOR, favor)
|
||||||
|
msg.Sort(kit.MDB_ID)
|
||||||
|
msg.Appendv(ice.MSG_APPEND, kit.MDB_TIME, kit.MDB_ID, kit.MDB_TEXT)
|
||||||
|
f.printf(m, msg.Table().Result())
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
if i, e := strconv.Atoi(line[1:]); e == nil {
|
||||||
|
// 历史命令
|
||||||
|
line = kit.Format(kit.Value(m.Cmd(web.FAVOR, favor, i).Optionv("value"), kit.MDB_TEXT))
|
||||||
|
} else {
|
||||||
|
f.printf(m, m.Cmd("history", "search", line[1:]).Table().Result())
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
} else if strings.TrimSpace(line) != "" && f.source == STDIO {
|
||||||
|
// 记录历史
|
||||||
|
m.Cmd(web.FAVOR, favor, "cmd", f.source, line)
|
||||||
}
|
}
|
||||||
return f
|
return line
|
||||||
}
|
}
|
||||||
func (f *Frame) printf(m *ice.Message, res string, arg ...interface{}) *Frame {
|
func (f *Frame) printf(m *ice.Message, res string, arg ...interface{}) *Frame {
|
||||||
if len(arg) > 0 {
|
if len(arg) > 0 {
|
||||||
fmt.Fprintf(f.out, res, arg...)
|
fmt.Fprintf(f.stdout, res, arg...)
|
||||||
} else {
|
} else {
|
||||||
fmt.Fprint(f.out, res)
|
fmt.Fprint(f.stdout, res)
|
||||||
}
|
}
|
||||||
// if !strings.HasSuffix(res, "\n") {
|
|
||||||
// fmt.Fprint(f.out, "\n")
|
|
||||||
// }
|
|
||||||
return f
|
return f
|
||||||
}
|
}
|
||||||
func (f *Frame) parse(m *ice.Message, line string) *Frame {
|
func (f *Frame) prompt(m *ice.Message, list ...string) *Frame {
|
||||||
for _, one := range kit.Split(line, ";", ";", ";") {
|
if f.stdout != os.Stdout {
|
||||||
ls := kit.Split(one)
|
return f
|
||||||
m.Log(ice.LOG_IMPORT, "stdin: %d %v", len(ls), ls)
|
}
|
||||||
|
if len(list) == 0 {
|
||||||
|
list = append(list, f.ps1...)
|
||||||
|
}
|
||||||
|
|
||||||
if len(ls) == 1 && ls[0] == "~" {
|
fmt.Fprintf(f.stdout, "\r")
|
||||||
// 模块列表
|
for _, v := range list {
|
||||||
ls = []string{"context"}
|
switch v {
|
||||||
} else if len(ls) > 0 && strings.HasPrefix(ls[0], "~") {
|
case "count":
|
||||||
// 切换模块
|
fmt.Fprintf(f.stdout, "%d", kit.Int(m.Conf("history", "meta.count"))+1)
|
||||||
target := ls[0][1:]
|
case "time":
|
||||||
if ls = ls[1:]; len(target) == 0 && len(ls) > 0 {
|
fmt.Fprintf(f.stdout, time.Now().Format("15:04:05"))
|
||||||
target, ls = ls[0], ls[1:]
|
case "target":
|
||||||
}
|
fmt.Fprintf(f.stdout, f.target.Name)
|
||||||
if target == "~" {
|
default:
|
||||||
target = ""
|
fmt.Fprintf(f.stdout, v)
|
||||||
}
|
|
||||||
m.Spawn(f.target).Search(target+".", func(p *ice.Context, s *ice.Context, key string) {
|
|
||||||
m.Info("choice: %s", s.Name)
|
|
||||||
f.target = s
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
if len(ls) == 0 {
|
}
|
||||||
continue
|
return f
|
||||||
|
}
|
||||||
|
func (f *Frame) option(m *ice.Message, ls []string) []string {
|
||||||
|
// 解析选项
|
||||||
|
ln := []string{}
|
||||||
|
m.Option("cache.limit", 10)
|
||||||
|
for i := 0; i < len(ls); i++ {
|
||||||
|
if ls[i] == "--" {
|
||||||
|
ln = append(ln, ls[i+1:]...)
|
||||||
|
break
|
||||||
|
} else if strings.HasPrefix(ls[i], "-") {
|
||||||
|
for j := i; j < len(ls); j++ {
|
||||||
|
if j == len(ls)-1 || strings.HasPrefix(ls[j+1], "-") {
|
||||||
|
if i == j {
|
||||||
|
m.Option(ls[i][1:], "true")
|
||||||
|
} else {
|
||||||
|
m.Option(ls[i][1:], ls[i+1:j+1])
|
||||||
|
}
|
||||||
|
i = j
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ln = append(ln, ls[i])
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
return ln
|
||||||
|
}
|
||||||
|
func (f *Frame) change(m *ice.Message, ls []string) []string {
|
||||||
|
if len(ls) == 1 && ls[0] == "~" {
|
||||||
|
// 模块列表
|
||||||
|
ls = []string{"context"}
|
||||||
|
} else if len(ls) > 0 && strings.HasPrefix(ls[0], "~") {
|
||||||
|
// 切换模块
|
||||||
|
target := ls[0][1:]
|
||||||
|
if ls = ls[1:]; len(target) == 0 && len(ls) > 0 {
|
||||||
|
target, ls = ls[0], ls[1:]
|
||||||
|
}
|
||||||
|
if target == "~" {
|
||||||
|
target = ""
|
||||||
|
}
|
||||||
|
m.Spawn(f.target).Search(target+".", func(p *ice.Context, s *ice.Context, key string) {
|
||||||
|
m.Info("choice: %s", s.Name)
|
||||||
|
f.target = s
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return ls
|
||||||
|
}
|
||||||
|
func (f *Frame) alias(m *ice.Message, ls []string) []string {
|
||||||
|
// 命令替换
|
||||||
|
if alias, ok := m.Optionv(ice.MSG_ALIAS).(map[string]interface{}); ok {
|
||||||
|
if a := kit.Simple(alias[ls[0]]); len(a) > 0 {
|
||||||
|
ls = append(append([]string{}, a...), ls[1:]...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ls
|
||||||
|
}
|
||||||
|
func (f *Frame) parse(m *ice.Message, line string) string {
|
||||||
|
for _, one := range kit.Split(line, ";", ";", ";") {
|
||||||
|
m.Log_IMPORT("stdin", one, "length", len(one))
|
||||||
|
|
||||||
|
ls := kit.Split(one)
|
||||||
if m.Option("scan_mode") == "scan" {
|
if m.Option("scan_mode") == "scan" {
|
||||||
f.printf(m, ls[0])
|
f.printf(m, ls[0])
|
||||||
f.printf(m, "`")
|
f.printf(m, "`")
|
||||||
@ -121,104 +194,47 @@ func (f *Frame) parse(m *ice.Message, line string) *Frame {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
// 命令替换
|
// 解析引擎
|
||||||
if alias, ok := m.Optionv(ice.MSG_ALIAS).(map[string]interface{}); ok {
|
|
||||||
if a := kit.Simple(alias[ls[0]]); len(a) > 0 {
|
|
||||||
ls = append(append([]string{}, a...), ls[1:]...)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 解析选项
|
|
||||||
ln := []string{}
|
|
||||||
msg := m.Spawns(f.target)
|
msg := m.Spawns(f.target)
|
||||||
msg.Option("cache.limit", 10)
|
|
||||||
for i := 0; i < len(ls); i++ {
|
|
||||||
if ls[i] == "--" {
|
|
||||||
ln = append(ln, ls[i+1:]...)
|
|
||||||
break
|
|
||||||
} else if strings.HasPrefix(ls[i], "-") {
|
|
||||||
for j := i; j < len(ls); j++ {
|
|
||||||
if j == len(ls)-1 || strings.HasPrefix(ls[j+1], "-") {
|
|
||||||
if i == j {
|
|
||||||
msg.Option(ls[i][1:], "true")
|
|
||||||
} else {
|
|
||||||
msg.Option(ls[i][1:], ls[i+1:j+1])
|
|
||||||
}
|
|
||||||
i = j
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
ln = append(ln, ls[i])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ln[0] == "qrcode" {
|
|
||||||
msg.Option(ice.MSG_OUTPUT, ice.RENDER_QRCODE)
|
|
||||||
ln = ln[1:]
|
|
||||||
}
|
|
||||||
msg.Option("_cmd", one)
|
msg.Option("_cmd", one)
|
||||||
|
ls = f.alias(msg, ls)
|
||||||
|
ls = f.change(msg, ls)
|
||||||
|
ls = f.option(msg, ls)
|
||||||
|
if len(ls) == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
// 执行命令
|
// 执行命令
|
||||||
msg.Cmdy(ln[0], ln[1:])
|
msg.Cmdy(ls[0], ls[1:])
|
||||||
|
|
||||||
// 渲染引擎
|
// 渲染引擎
|
||||||
_args, _ := msg.Optionv(ice.MSG_ARGS).([]interface{})
|
_args, _ := msg.Optionv(ice.MSG_ARGS).([]interface{})
|
||||||
Render(msg, msg.Option(ice.MSG_OUTPUT), _args...)
|
Render(msg, msg.Option(ice.MSG_OUTPUT), _args...)
|
||||||
|
|
||||||
}
|
}
|
||||||
return f
|
return ""
|
||||||
}
|
}
|
||||||
|
func (f *Frame) scan(m *ice.Message, file, line string, r io.Reader) *Frame {
|
||||||
|
f.ps1 = kit.Simple(m.Confv("prompt", "meta.PS1"))
|
||||||
|
f.ps2 = kit.Simple(m.Confv("prompt", "meta.PS2"))
|
||||||
|
ps := f.ps1
|
||||||
|
|
||||||
func (f *Frame) Spawn(m *ice.Message, c *ice.Context, arg ...string) ice.Server {
|
m.I, m.O = r, f.stdout
|
||||||
return &Frame{}
|
bio := bufio.NewScanner(r)
|
||||||
}
|
for f.prompt(m, ps...); bio.Scan() && !f.exit; f.prompt(m, ps...) {
|
||||||
func (f *Frame) Begin(m *ice.Message, arg ...string) ice.Server {
|
|
||||||
return f
|
|
||||||
}
|
|
||||||
func (f *Frame) Start(m *ice.Message, arg ...string) bool {
|
|
||||||
m.Option(ice.MSG_PROMPT, m.Confv("prompt", "meta.PS1"))
|
|
||||||
f.target = m.Source()
|
|
||||||
aaa.UserRoot(m)
|
|
||||||
|
|
||||||
switch kit.Select("stdio", arg, 0) {
|
|
||||||
case "stdio":
|
|
||||||
// 解析终端
|
|
||||||
f.in, f.out = os.Stdin, os.Stdout
|
|
||||||
m.Cap(ice.CTX_STREAM, "stdio")
|
|
||||||
f.target = m.Target()
|
|
||||||
default:
|
|
||||||
if s, e := os.Open(arg[0]); m.Warn(e != nil, "%s", e) {
|
|
||||||
// 打开失败
|
|
||||||
return true
|
|
||||||
} else {
|
|
||||||
// 解析脚本
|
|
||||||
defer s.Close()
|
|
||||||
if f.in, f.out = s, os.Stdout; m.Optionv(ice.MSG_STDOUT) != nil {
|
|
||||||
f.out = m.Optionv(ice.MSG_STDOUT).(io.Writer)
|
|
||||||
}
|
|
||||||
m.Cap(ice.CTX_STREAM, arg[0])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
m.I, m.O = f.in, f.out
|
|
||||||
|
|
||||||
line := ""
|
|
||||||
bio := bufio.NewScanner(f.in)
|
|
||||||
for f.prompt(m); bio.Scan() && !f.exit; f.prompt(m) {
|
|
||||||
if len(bio.Text()) == 0 {
|
if len(bio.Text()) == 0 {
|
||||||
// 空行
|
// 空行
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if strings.HasSuffix(bio.Text(), "\\") {
|
if strings.HasSuffix(bio.Text(), "\\") {
|
||||||
// 续行
|
// 续行
|
||||||
m.Option(ice.MSG_PROMPT, m.Confv("prompt", "meta.PS2"))
|
|
||||||
line += bio.Text()[:len(bio.Text())-1]
|
line += bio.Text()[:len(bio.Text())-1]
|
||||||
|
ps = f.ps2
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if line += bio.Text(); strings.Count(line, "`")%2 == 1 {
|
if line += bio.Text(); strings.Count(line, "`")%2 == 1 {
|
||||||
// 多行
|
// 多行
|
||||||
m.Option(ice.MSG_PROMPT, m.Confv("prompt", "meta.PS2"))
|
|
||||||
line += "\n"
|
line += "\n"
|
||||||
|
ps = f.ps2
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if strings.HasPrefix(strings.TrimSpace(line), "#") {
|
if strings.HasPrefix(strings.TrimSpace(line), "#") {
|
||||||
@ -226,127 +242,127 @@ func (f *Frame) Start(m *ice.Message, arg ...string) bool {
|
|||||||
line = ""
|
line = ""
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
if line = f.history(m, line); line == "" {
|
||||||
if strings.HasPrefix(strings.TrimSpace(line), "!") {
|
// 历史命令
|
||||||
if len(line) == 1 {
|
continue
|
||||||
// 历史记录
|
|
||||||
f.printf(m, m.Cmd("history").Table().Result())
|
|
||||||
line = ""
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if i, e := strconv.Atoi(line[1:]); e == nil {
|
|
||||||
// 历史命令
|
|
||||||
m.Grows("history", nil, "id", kit.Format(i), func(index int, value map[string]interface{}) {
|
|
||||||
line = kit.Format(value["line"])
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
f.printf(m, m.Cmd("history", "search", line[1:]).Table().Result())
|
|
||||||
line = ""
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// 记录历史
|
|
||||||
m.Grow("history", nil, kit.Dict("line", line))
|
|
||||||
}
|
}
|
||||||
|
if ps = f.ps1; f.stdout == os.Stdout {
|
||||||
// 清空格式
|
// 清空格式
|
||||||
if m.Option(ice.MSG_PROMPT, m.Confv("prompt", "meta.PS1")); f.out == os.Stdout {
|
|
||||||
f.printf(m, "\033[0m")
|
f.printf(m, "\033[0m")
|
||||||
}
|
}
|
||||||
if m.Cap(ice.CTX_STREAM) == "stdio" {
|
line = f.parse(m, line)
|
||||||
m.Cmd(ice.WEB_FAVOR, "cmd.history", "cmd", kit.Select("stdio", arg, 0), line)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 解析命令
|
|
||||||
f.parse(m, line)
|
|
||||||
m.Cost("stdin: %v", line)
|
|
||||||
line = ""
|
|
||||||
}
|
}
|
||||||
|
return f
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *Frame) Begin(m *ice.Message, arg ...string) ice.Server {
|
||||||
|
return f
|
||||||
|
}
|
||||||
|
func (f *Frame) Spawn(m *ice.Message, c *ice.Context, arg ...string) ice.Server {
|
||||||
|
return &Frame{}
|
||||||
|
}
|
||||||
|
func (f *Frame) Start(m *ice.Message, arg ...string) bool {
|
||||||
|
var r io.Reader
|
||||||
|
switch kit.Select(STDIO, arg, 0) {
|
||||||
|
case STDIO:
|
||||||
|
// 终端交互
|
||||||
|
f.source = STDIO
|
||||||
|
r, f.stdout = os.Stdin, os.Stdout
|
||||||
|
m.Cap(ice.CTX_STREAM, STDIO)
|
||||||
|
f.target = m.Target()
|
||||||
|
aaa.UserRoot(m)
|
||||||
|
default:
|
||||||
|
|
||||||
|
if s, e := os.Open(arg[0]); !m.Warn(e != nil, "%s", e) {
|
||||||
|
defer s.Close()
|
||||||
|
|
||||||
|
buf := bytes.NewBuffer(make([]byte, 0, 4096))
|
||||||
|
defer m.Echo(buf.String())
|
||||||
|
|
||||||
|
// 脚本解析
|
||||||
|
f.source = arg[0]
|
||||||
|
r, f.stdout = s, buf
|
||||||
|
m.Cap(ice.CTX_STREAM, arg[0])
|
||||||
|
f.target = m.Source()
|
||||||
|
break
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
f.scan(m, kit.Select(STDIO, arg, 0), "", r)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
func (f *Frame) Close(m *ice.Message, arg ...string) bool {
|
func (f *Frame) Close(m *ice.Message, arg ...string) bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
SOURCE = "source"
|
||||||
|
TARGET = "target"
|
||||||
|
PROMPT = "prompt"
|
||||||
|
QRCODE = "qrcode"
|
||||||
|
RETURN = "return"
|
||||||
|
REMOTE = "remote"
|
||||||
|
)
|
||||||
|
const (
|
||||||
|
STDIO = "stdio"
|
||||||
|
)
|
||||||
|
|
||||||
var Index = &ice.Context{Name: "ssh", Help: "终端模块",
|
var Index = &ice.Context{Name: "ssh", Help: "终端模块",
|
||||||
Caches: map[string]*ice.Cache{},
|
Caches: map[string]*ice.Cache{},
|
||||||
Configs: map[string]*ice.Config{
|
Configs: map[string]*ice.Config{
|
||||||
"history": {Name: "history", Help: "history", Value: kit.Data("limit", "200", "least", "100")},
|
SOURCE: {Name: "prompt", Help: "命令提示", Value: kit.Data(
|
||||||
"prompt": {Name: "prompt", Help: "prompt", Value: kit.Data(
|
web.FAVOR, "cmd.history",
|
||||||
|
)},
|
||||||
|
PROMPT: {Name: "prompt", Help: "命令提示", Value: kit.Data(
|
||||||
"PS1", []interface{}{"\033[33;44m", "count", "[", "time", "]", "\033[5m", "target", "\033[0m", "\033[44m", ">", "\033[0m ", "\033[?25h", "\033[32m"},
|
"PS1", []interface{}{"\033[33;44m", "count", "[", "time", "]", "\033[5m", "target", "\033[0m", "\033[44m", ">", "\033[0m ", "\033[?25h", "\033[32m"},
|
||||||
"PS2", []interface{}{"count", " ", "target", "> "},
|
"PS2", []interface{}{"count", " ", "target", "> "},
|
||||||
)},
|
)},
|
||||||
|
REMOTE: {Name: "remote", Help: "远程连接", Value: kit.Data()},
|
||||||
"super": {Name: "super", Help: "super", Value: kit.Data()},
|
|
||||||
},
|
},
|
||||||
Commands: map[string]*ice.Command{
|
Commands: map[string]*ice.Command{
|
||||||
ice.ICE_INIT: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
|
ice.ICE_INIT: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { m.Load() }},
|
||||||
m.Load()
|
|
||||||
}},
|
|
||||||
ice.ICE_EXIT: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
|
ice.ICE_EXIT: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
|
||||||
m.Save("history")
|
if _, ok := m.Target().Server().(*Frame); ok {
|
||||||
|
|
||||||
if f, ok := m.Target().Server().(*Frame); ok {
|
|
||||||
// 关闭终端
|
|
||||||
f.in.Close()
|
|
||||||
m.Done()
|
m.Done()
|
||||||
}
|
}
|
||||||
}},
|
}},
|
||||||
|
|
||||||
"history": {Name: "history", Help: "历史", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
|
SOURCE: {Name: "source file", Help: "脚本解析", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
|
||||||
if len(arg) == 0 {
|
m.Starts(strings.Replace(arg[0], ".", "_", -1), arg[0], arg[0:]...)
|
||||||
m.Grows("history", nil, "", "", func(index int, value map[string]interface{}) {
|
|
||||||
m.Push("", value, []string{"id", "time", "line"})
|
|
||||||
})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
switch arg[0] {
|
|
||||||
case "search":
|
|
||||||
m.Grows("history", nil, "", "", func(index int, value map[string]interface{}) {
|
|
||||||
if strings.Contains(kit.Format(value["line"]), arg[1]) {
|
|
||||||
m.Push("", value, []string{"id", "time", "line"})
|
|
||||||
}
|
|
||||||
})
|
|
||||||
default:
|
|
||||||
m.Grows("history", nil, "id", arg[0], func(index int, value map[string]interface{}) {
|
|
||||||
m.Push("", value, []string{"id", "time", "line"})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}},
|
}},
|
||||||
"return": {Name: "return", Help: "解析", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
|
TARGET: {Name: "target name", Help: "当前模块", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
|
||||||
m.Option(ice.MSG_PROMPT, m.Confv("prompt", "meta.PS1"))
|
m.Search(arg[0], func(p *ice.Context, s *ice.Context, key string) {
|
||||||
|
f := m.Target().Server().(*Frame)
|
||||||
|
f.target = s
|
||||||
|
f.prompt(m)
|
||||||
|
})
|
||||||
|
}},
|
||||||
|
PROMPT: {Name: "prompt arg...", Help: "命令提示", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
|
||||||
|
f := m.Target().Server().(*Frame)
|
||||||
|
f.ps1 = arg
|
||||||
|
f.prompt(m)
|
||||||
|
}},
|
||||||
|
QRCODE: {Name: "qrcode arg...", Help: "命令提示", Action: map[string]*ice.Action{
|
||||||
|
"json": {Name: "json [key val]...", Help: "json", Hand: func(m *ice.Message, arg ...string) {
|
||||||
|
val := map[string]interface{}{}
|
||||||
|
for i := 0; i < len(arg)-1; i += 2 {
|
||||||
|
kit.Value(val, arg[i], arg[i+1])
|
||||||
|
}
|
||||||
|
f := m.Target().Server().(*Frame)
|
||||||
|
f.printf(m, m.Cmdx(cli.PYTHON, "qrcode", kit.Format(val)))
|
||||||
|
}},
|
||||||
|
}, Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
|
||||||
|
f := m.Target().Server().(*Frame)
|
||||||
|
f.printf(m, m.Cmdx(cli.PYTHON, "qrcode", strings.Join(arg, "")))
|
||||||
|
}},
|
||||||
|
RETURN: {Name: "return", Help: "结束脚本", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
|
||||||
f := m.Target().Server().(*Frame)
|
f := m.Target().Server().(*Frame)
|
||||||
f.exit = true
|
f.exit = true
|
||||||
}},
|
}},
|
||||||
"target": {Name: "target", Help: "目标", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
|
|
||||||
f := m.Target().Server().(*Frame)
|
|
||||||
m.Search(arg[0], func(p *ice.Context, s *ice.Context, key string) {
|
|
||||||
f.target = s
|
|
||||||
})
|
|
||||||
f.prompt(m)
|
|
||||||
}},
|
|
||||||
"source": {Name: "source file", Help: "解析", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
|
|
||||||
buf := bytes.NewBuffer(make([]byte, 0, 4096))
|
|
||||||
m.Optionv(ice.MSG_STDOUT, buf)
|
|
||||||
|
|
||||||
m.Starts(strings.Replace(arg[0], ".", "_", -1), arg[0], arg[0:]...)
|
REMOTE: {Name: "remote user remote port local", Help: "远程连接", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
|
||||||
m.Echo(buf.String())
|
key := m.Rich(REMOTE, nil, kit.Dict(
|
||||||
}},
|
|
||||||
"show": {Name: "show", Help: "解析", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
|
|
||||||
f, e := os.Open("usr/local/what/hi.shy")
|
|
||||||
m.Assert(e)
|
|
||||||
|
|
||||||
bio := bufio.NewScanner(f)
|
|
||||||
for bio.Scan() {
|
|
||||||
ls := kit.Split(bio.Text())
|
|
||||||
m.Echo("%d: %v\n", len(ls), ls)
|
|
||||||
m.Info("%v", ls)
|
|
||||||
}
|
|
||||||
}},
|
|
||||||
|
|
||||||
"super": {Name: "super user remote port local", Help: "上位机", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
|
|
||||||
key := m.Rich("super", nil, kit.Dict(
|
|
||||||
"user", arg[0], "remote", arg[1], "port", arg[2], "local", arg[3],
|
"user", arg[0], "remote", arg[1], "port", arg[2], "local", arg[3],
|
||||||
))
|
))
|
||||||
m.Echo(key)
|
m.Echo(key)
|
||||||
@ -354,17 +370,13 @@ var Index = &ice.Context{Name: "ssh", Help: "终端模块",
|
|||||||
|
|
||||||
m.Gos(m, func(m *ice.Message) {
|
m.Gos(m, func(m *ice.Message) {
|
||||||
for {
|
for {
|
||||||
m.Cmd(ice.CLI_SYSTEM, "ssh", "-CNR", kit.Format("%s:%s:22", arg[2], arg[3]), kit.Format("%s@%s", arg[0], arg[1]))
|
m.Cmd(cli.SYSTEM, "ssh", "-CNR", kit.Format("%s:%s:22", arg[2], kit.Select("localhost", arg, 3)),
|
||||||
|
kit.Format("%s@%s", arg[0], arg[1]))
|
||||||
m.Info("reconnect after 10s")
|
m.Info("reconnect after 10s")
|
||||||
time.Sleep(time.Second * 10)
|
time.Sleep(time.Second * 10)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}},
|
}},
|
||||||
|
|
||||||
"what": {Name: "what", Help: "上位机", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
|
|
||||||
ls := kit.Split("window:=auto", " ", ":=")
|
|
||||||
m.Echo("%v %v", len(ls), ls)
|
|
||||||
}},
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -384,6 +384,9 @@ func StoryAdd(m *ice.Message, mime string, name string, text string, arg ...stri
|
|||||||
}
|
}
|
||||||
|
|
||||||
const STORY = "story"
|
const STORY = "story"
|
||||||
|
const (
|
||||||
|
CATCH = "catch"
|
||||||
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
Index.Merge(&ice.Context{
|
Index.Merge(&ice.Context{
|
||||||
|
@ -2,7 +2,6 @@ package wiki
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/shylinux/icebergs"
|
"github.com/shylinux/icebergs"
|
||||||
"github.com/shylinux/icebergs/base/nfs"
|
|
||||||
"github.com/shylinux/toolkits"
|
"github.com/shylinux/toolkits"
|
||||||
|
|
||||||
"path"
|
"path"
|
||||||
@ -36,7 +35,7 @@ func init() {
|
|||||||
"display", "/plugin/local/wiki/draw.js",
|
"display", "/plugin/local/wiki/draw.js",
|
||||||
), Action: map[string]*ice.Action{
|
), Action: map[string]*ice.Action{
|
||||||
"save": {Name: "save path text", Help: "保存", Hand: func(m *ice.Message, arg ...string) {
|
"save": {Name: "save path text", Help: "保存", Hand: func(m *ice.Message, arg ...string) {
|
||||||
nfs.FileSave(m, path.Join(m.Conf(DRAW, "meta.path"), kit.Select("hi.svg", arg, 0)), kit.Select(m.Option("content"), arg, 1))
|
m.Cmd("nfs.save", path.Join(m.Conf(DRAW, "meta.path"), kit.Select("hi.svg", arg, 0)), kit.Select(m.Option("content"), arg, 1))
|
||||||
}},
|
}},
|
||||||
"run": {Name: "show path text", Help: "运行", Hand: func(m *ice.Message, arg ...string) {
|
"run": {Name: "show path text", Help: "运行", Hand: func(m *ice.Message, arg ...string) {
|
||||||
_draw_show(m, arg[0], arg[1], arg[2], arg[3], arg[4:]...)
|
_draw_show(m, arg[0], arg[1], arg[2], arg[3], arg[4:]...)
|
||||||
|
2
data.go
2
data.go
@ -342,7 +342,7 @@ func (m *Message) Grows(key string, chain interface{}, match string, value strin
|
|||||||
order := 0
|
order := 0
|
||||||
if begin < current {
|
if begin < current {
|
||||||
// 读取文件
|
// 读取文件
|
||||||
m.Log(LOG_INFO, "%s.%v read %v-%v from %v-%v", key, chain, begin, end, current, current+len(list))
|
// m.Log(LOG_INFO, "%s.%v read %v-%v from %v-%v", key, chain, begin, end, current, current+len(list))
|
||||||
store, _ := meta["record"].([]interface{})
|
store, _ := meta["record"].([]interface{})
|
||||||
for s := len(store) - 1; s > -1; s-- {
|
for s := len(store) - 1; s > -1; s-- {
|
||||||
item, _ := store[s].(map[string]interface{})
|
item, _ := store[s].(map[string]interface{})
|
||||||
|
7
exec.go
7
exec.go
@ -9,6 +9,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
kit "github.com/shylinux/toolkits"
|
kit "github.com/shylinux/toolkits"
|
||||||
|
"github.com/shylinux/toolkits/task"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (m *Message) TryCatch(msg *Message, safe bool, hand ...func(msg *Message)) *Message {
|
func (m *Message) TryCatch(msg *Message, safe bool, hand ...func(msg *Message)) *Message {
|
||||||
@ -112,6 +113,10 @@ func (m *Message) Back(res *Message) *Message {
|
|||||||
return m
|
return m
|
||||||
}
|
}
|
||||||
func (m *Message) Gos(msg *Message, cb func(*Message)) *Message {
|
func (m *Message) Gos(msg *Message, cb func(*Message)) *Message {
|
||||||
go func() { msg.TryCatch(msg, true, func(msg *Message) { cb(msg) }) }()
|
task.Put(nil, func(task *task.Task) error {
|
||||||
|
msg.Optionv("_task", task)
|
||||||
|
msg.TryCatch(msg, true, func(msg *Message) { cb(msg) })
|
||||||
|
return nil
|
||||||
|
})
|
||||||
return m
|
return m
|
||||||
}
|
}
|
||||||
|
9
meta.go
9
meta.go
@ -52,6 +52,11 @@ func (m *Message) Set(key string, arg ...string) *Message {
|
|||||||
}
|
}
|
||||||
func (m *Message) Push(key string, value interface{}, arg ...interface{}) *Message {
|
func (m *Message) Push(key string, value interface{}, arg ...interface{}) *Message {
|
||||||
switch value := value.(type) {
|
switch value := value.(type) {
|
||||||
|
case map[string]string:
|
||||||
|
for k, v := range value {
|
||||||
|
m.Push(k, v)
|
||||||
|
}
|
||||||
|
return m
|
||||||
case map[string]interface{}:
|
case map[string]interface{}:
|
||||||
if key == "detail" {
|
if key == "detail" {
|
||||||
// 格式转换
|
// 格式转换
|
||||||
@ -452,6 +457,10 @@ func (m *Message) Append(key string, arg ...interface{}) string {
|
|||||||
return kit.Select("", m.Appendv(key, arg...), 0)
|
return kit.Select("", m.Appendv(key, arg...), 0)
|
||||||
}
|
}
|
||||||
func (m *Message) Appendv(key string, arg ...interface{}) []string {
|
func (m *Message) Appendv(key string, arg ...interface{}) []string {
|
||||||
|
if key == MSG_APPEND {
|
||||||
|
m.meta[MSG_APPEND] = kit.Simple(arg)
|
||||||
|
return m.meta[key]
|
||||||
|
}
|
||||||
if key == "_index" {
|
if key == "_index" {
|
||||||
max := 0
|
max := 0
|
||||||
for _, k := range m.meta[MSG_APPEND] {
|
for _, k := range m.meta[MSG_APPEND] {
|
||||||
|
@ -47,7 +47,7 @@ func _alpha_find2(m *ice.Message, method, word string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var mu sync.Mutex
|
var mu sync.Mutex
|
||||||
task.Sync(args, func(task *task.Task) error {
|
task.Sync(args, func(task *task.Task, lock *task.Lock) error {
|
||||||
info := task.Arg.(os.FileInfo)
|
info := task.Arg.(os.FileInfo)
|
||||||
file := path.Join(p, info.Name())
|
file := path.Join(p, info.Name())
|
||||||
kit.CSV(file, 100000, func(index int, value map[string]string, head []string) {
|
kit.CSV(file, 100000, func(index int, value map[string]string, head []string) {
|
||||||
|
@ -90,7 +90,7 @@ func _input_find2(m *ice.Message, method, word, limit string) {
|
|||||||
defer m.Cost("some")
|
defer m.Cost("some")
|
||||||
|
|
||||||
var mu sync.Mutex
|
var mu sync.Mutex
|
||||||
task.Sync(list, func(task *task.Task) error {
|
task.Sync(list, func(task *task.Task, lock *task.Lock) error {
|
||||||
kit.CSV(kit.Format(task.Arg), 100000, func(index int, value map[string]string, head []string) {
|
kit.CSV(kit.Format(task.Arg), 100000, func(index int, value map[string]string, head []string) {
|
||||||
if value["code"] != word {
|
if value["code"] != word {
|
||||||
return
|
return
|
||||||
@ -181,7 +181,7 @@ var Index = &ice.Context{Name: "input", Help: "输入法",
|
|||||||
Configs: map[string]*ice.Config{
|
Configs: map[string]*ice.Config{
|
||||||
INPUT: {Name: "input", Help: "输入法", Value: kit.Data(
|
INPUT: {Name: "input", Help: "输入法", Value: kit.Data(
|
||||||
"repos", "wubi-dict", "local", "person",
|
"repos", "wubi-dict", "local", "person",
|
||||||
kit.MDB_STORE, "var/data/input", kit.MDB_FSIZE, "200000",
|
kit.MDB_STORE, "usr/export/input", kit.MDB_FSIZE, "200000",
|
||||||
kit.MDB_LIMIT, "5000", kit.MDB_LEAST, "1000",
|
kit.MDB_LIMIT, "5000", kit.MDB_LEAST, "1000",
|
||||||
kit.MDB_SHORT, "zone",
|
kit.MDB_SHORT, "zone",
|
||||||
)},
|
)},
|
||||||
|
19
type.go
19
type.go
@ -78,6 +78,9 @@ func (c *Context) Cap(key string, arg ...interface{}) string {
|
|||||||
return c.Caches[key].Value
|
return c.Caches[key].Value
|
||||||
}
|
}
|
||||||
func (c *Context) Run(m *Message, cmd *Command, key string, arg ...string) *Message {
|
func (c *Context) Run(m *Message, cmd *Command, key string, arg ...string) *Message {
|
||||||
|
if cmd == nil {
|
||||||
|
return m
|
||||||
|
}
|
||||||
m.meta[MSG_DETAIL] = kit.Simple(key, arg)
|
m.meta[MSG_DETAIL] = kit.Simple(key, arg)
|
||||||
m.Hand = true
|
m.Hand = true
|
||||||
|
|
||||||
@ -100,7 +103,7 @@ func (c *Context) Run(m *Message, cmd *Command, key string, arg ...string) *Mess
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if len(arg) > 0 {
|
if len(arg) > 0 && cmd.Action != nil {
|
||||||
if h, ok := cmd.Action[arg[0]]; ok {
|
if h, ok := cmd.Action[arg[0]]; ok {
|
||||||
m.Log(LOG_CMDS, "%s.%s %d %v %s", c.Name, key, len(arg), arg, kit.FileLine(h.Hand, 3))
|
m.Log(LOG_CMDS, "%s.%s %d %v %s", c.Name, key, len(arg), arg, kit.FileLine(h.Hand, 3))
|
||||||
h.Hand(m, arg[1:]...)
|
h.Hand(m, arg[1:]...)
|
||||||
@ -499,7 +502,9 @@ func (m *Message) Search(key interface{}, cb interface{}) *Message {
|
|||||||
|
|
||||||
// 查找模块
|
// 查找模块
|
||||||
p := m.target.root
|
p := m.target.root
|
||||||
if strings.Contains(key, ":") {
|
if ctx, ok := names[key].(*Context); ok {
|
||||||
|
p = ctx
|
||||||
|
} else if strings.Contains(key, ":") {
|
||||||
|
|
||||||
} else if key == "." {
|
} else if key == "." {
|
||||||
if m.target.context != nil {
|
if m.target.context != nil {
|
||||||
@ -597,14 +602,10 @@ func (m *Message) Cmd(arg ...interface{}) *Message {
|
|||||||
return m
|
return m
|
||||||
}
|
}
|
||||||
|
|
||||||
if ctx, ok := names[list[0]].(*Context); ok {
|
|
||||||
m.Hand = true
|
|
||||||
return ctx.Run(m.Spawns(ctx), ctx.Commands[list[0]], list[0], list[1:]...)
|
|
||||||
}
|
|
||||||
|
|
||||||
m.Search(list[0], func(p *Context, c *Context, key string, cmd *Command) {
|
m.Search(list[0], func(p *Context, c *Context, key string, cmd *Command) {
|
||||||
m = p.Run(m.Spawns(c), cmd, key, list[1:]...)
|
m.TryCatch(m.Spawns(c), true, func(msg *Message) {
|
||||||
m.Hand = true
|
m = p.Run(msg, cmd, key, list[1:]...)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
if m.Warn(m.Hand == false, "not found %v", list) {
|
if m.Warn(m.Hand == false, "not found %v", list) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user