1
0
forked from x/icebergs
This commit is contained in:
shaoying 2020-09-29 19:25:13 +08:00
parent 75f8a0ccec
commit aa94fbf78a
17 changed files with 250 additions and 334 deletions

View File

@ -16,18 +16,17 @@ func _file_name(m *ice.Message, arg ...string) string {
}
func _hash_insert(m *ice.Message, prefix, chain string, arg ...string) {
m.Log_INSERT(kit.MDB_PREFIX, prefix, arg[0], arg[1])
m.Log_INSERT(kit.MDB_KEY, path.Join(prefix, chain), arg[0], arg[1])
m.Echo(m.Rich(prefix, chain, kit.Data(arg)))
}
func _hash_delete(m *ice.Message, prefix, chain, field, value string) {
m.Richs(prefix, chain, value, func(key string, val map[string]interface{}) {
m.Log_DELETE(kit.MDB_PREFIX, prefix, field, value, kit.MDB_VALUE, kit.Format(val))
m.Log_DELETE(kit.MDB_KEY, path.Join(prefix, chain), field, value, kit.MDB_VALUE, kit.Format(val))
m.Conf(prefix, kit.Keys(chain, kit.MDB_HASH, key), "")
})
}
func _hash_select(m *ice.Message, prefix, chain, field, value string) {
if field == kit.MDB_HASH && value == "random" {
if field == kit.MDB_HASH && value == RANDOM {
value = kit.MDB_RANDOMS
}
fields := kit.Split(kit.Select("time,hash,type,name,text", m.Option(FIELDS)))
@ -56,7 +55,7 @@ func _hash_modify(m *ice.Message, prefix, chain string, field, value string, arg
}
kit.Value(val, arg[i], arg[i+1])
}
m.Log_MODIFY(kit.MDB_PREFIX, prefix, field, value, arg)
m.Log_MODIFY(kit.MDB_KEY, path.Join(prefix, chain), field, value, arg)
})
}
func _hash_export(m *ice.Message, prefix, chain, file string) {
@ -68,7 +67,7 @@ func _hash_export(m *ice.Message, prefix, chain, file string) {
en.SetIndent("", " ")
en.Encode(m.Confv(prefix, kit.Keys(chain, HASH)))
m.Log_EXPORT(kit.MDB_FILE, p)
m.Log_EXPORT(kit.MDB_KEY, path.Join(prefix, chain), kit.MDB_FILE, p)
m.Echo(p)
}
func _hash_import(m *ice.Message, prefix, chain, file string) {
@ -95,10 +94,11 @@ func _hash_import(m *ice.Message, prefix, chain, file string) {
}
}
m.Log_IMPORT(kit.MDB_PREFIX, prefix, kit.MDB_COUNT, count)
m.Log_IMPORT(kit.MDB_KEY, path.Join(prefix, chain), kit.MDB_COUNT, count)
m.Echo("%d", count)
}
func _hash_prunes(m *ice.Message, prefix, chain string, arg ...string) {
fields := kit.Split(kit.Select("time,hash,type,name,text", m.Option(FIELDS)))
m.Richs(prefix, chain, kit.MDB_FOREACH, func(key string, val map[string]interface{}) {
if val[kit.MDB_META] != nil {
val = val[kit.MDB_META].(map[string]interface{})
@ -108,8 +108,10 @@ func _hash_prunes(m *ice.Message, prefix, chain string, arg ...string) {
return
}
}
_hash_delete(m, prefix, chain, kit.MDB_HASH, key)
m.Push(key, val)
m.Push(key, val, fields)
})
m.Table(func(index int, value map[string]string, head []string) {
_hash_delete(m, prefix, chain, kit.MDB_HASH, value[kit.MDB_HASH])
})
}
func _hash_inputs(m *ice.Message, prefix, chain string, field, value string) {
@ -132,7 +134,7 @@ func _hash_inputs(m *ice.Message, prefix, chain string, field, value string) {
}
func _list_insert(m *ice.Message, prefix, chain string, arg ...string) {
m.Log_INSERT(kit.MDB_PREFIX, prefix, arg[0], arg[1])
m.Log_INSERT(kit.MDB_KEY, path.Join(prefix, chain), arg[0], arg[1])
m.Echo("%d", m.Grow(prefix, chain, kit.Dict(arg)))
}
func _list_delete(m *ice.Message, prefix, chain, field, value string) {
@ -143,11 +145,10 @@ func _list_select(m *ice.Message, prefix, chain, field, value string) {
if val[kit.MDB_META] != nil {
val = val[kit.MDB_META].(map[string]interface{})
}
if m.Option(FIELDS) == DETAIL {
m.Push(DETAIL, val)
} else {
m.Push(kit.Format(index), val, fields)
m.Push("", val, fields)
}
})
if m.Option(FIELDS) != DETAIL {
@ -165,7 +166,7 @@ func _list_modify(m *ice.Message, prefix, chain string, field, value string, arg
}
kit.Value(val, arg[i], arg[i+1])
}
m.Log_MODIFY(kit.MDB_PREFIX, prefix, field, value, arg)
m.Log_MODIFY(kit.MDB_KEY, path.Join(prefix, chain), field, value, arg)
})
}
func _list_export(m *ice.Message, prefix, chain, file string) {
@ -178,10 +179,14 @@ func _list_export(m *ice.Message, prefix, chain, file string) {
count := 0
head := kit.Split(m.Option(FIELDS))
m.Grows(prefix, chain, "", "", func(index int, value map[string]interface{}) {
m.Grows(prefix, chain, "", "", func(index int, val map[string]interface{}) {
if val[kit.MDB_META] != nil {
val = val[kit.MDB_META].(map[string]interface{})
}
if index == 0 && len(head) == 0 {
// 输出表头
for k := range value {
for k := range val {
head = append(head, k)
}
sort.Strings(head)
@ -191,13 +196,13 @@ func _list_export(m *ice.Message, prefix, chain, file string) {
// 输出数据
data := []string{}
for _, k := range head {
data = append(data, kit.Format(value[k]))
data = append(data, kit.Format(val[k]))
}
w.Write(data)
count++
})
m.Log_EXPORT(kit.MDB_FILE, p, kit.MDB_COUNT, count)
m.Log_EXPORT(kit.MDB_KEY, path.Join(prefix, chain), kit.MDB_FILE, p, kit.MDB_COUNT, count)
m.Echo(p)
}
func _list_import(m *ice.Message, prefix, chain, file string) {
@ -218,9 +223,9 @@ func _list_import(m *ice.Message, prefix, chain, file string) {
data := kit.Dict()
for i, k := range head {
if k == kit.MDB_EXTRA {
data[k] = kit.UnMarshal(line[i])
kit.Value(data, k, kit.UnMarshal(line[i]))
} else {
data[k] = line[i]
kit.Value(data, k, line[i])
}
}
@ -231,6 +236,8 @@ func _list_import(m *ice.Message, prefix, chain, file string) {
m.Log_IMPORT(kit.MDB_KEY, kit.Keys(prefix, chain), kit.MDB_COUNT, count)
m.Echo("%d", count)
}
func _list_prunes(m *ice.Message, prefix, chain string, arg ...string) {
}
func _list_inputs(m *ice.Message, prefix, chain string, field, value string) {
list := map[string]int{}
m.Grows(prefix, chain, "", "", func(index int, val map[string]interface{}) {
@ -254,7 +261,11 @@ func _zone_select(m *ice.Message, prefix, chain, zone string, id string) {
val = val[kit.MDB_META].(map[string]interface{})
}
if zone == "" {
m.Push(key, val, fields)
if m.Option(FIELDS) == DETAIL {
m.Push(DETAIL, val)
} else {
m.Push(key, val, fields)
}
return
}
@ -266,6 +277,8 @@ func _zone_select(m *ice.Message, prefix, chain, zone string, id string) {
switch cb := cb.(type) {
case func(string, map[string]interface{}, map[string]interface{}):
cb(key, value, val)
case func(string, map[string]interface{}):
cb(key, value)
default:
if m.Option(FIELDS) == DETAIL {
m.Push(DETAIL, value)
@ -300,14 +313,14 @@ func _zone_export(m *ice.Message, prefix, chain, file string) {
list := []string{}
for _, k := range fields {
list = append(list, kit.Select(kit.Format(val[k]), kit.Format(value[k])))
list = append(list, kit.Select(kit.Format(kit.Value(val, k)), kit.Format(kit.Value(value, k))))
}
w.Write(list)
count++
})
})
m.Log_EXPORT(kit.MDB_FILE, p, kit.MDB_COUNT, count)
m.Log_EXPORT(kit.MDB_KEY, path.Join(prefix, chain), kit.MDB_FILE, p, kit.MDB_COUNT, count)
m.Echo(p)
}
func _zone_import(m *ice.Message, prefix, chain, file string) {
@ -343,14 +356,14 @@ func _zone_import(m *ice.Message, prefix, chain, file string) {
}
}
if list[zone] == "" {
list[zone] = m.Rich(prefix, chain, kit.Dict(zkey, zone))
list[zone] = m.Rich(prefix, chain, kit.Data(zkey, zone))
}
m.Grow(prefix, kit.Keys(chain, kit.MDB_HASH, list[zone]), data)
count++
}
m.Log_IMPORT(kit.MDB_PREFIX, prefix, kit.MDB_COUNT, count)
m.Log_IMPORT(kit.MDB_KEY, path.Join(prefix, chain), kit.MDB_COUNT, count)
m.Echo("%d", count)
}
@ -368,9 +381,7 @@ const (
const (
FIELDS = "fields"
DETAIL = "detail"
INVITE = "invite"
COMMIT = "commit"
RANDOM = "random"
CREATE = "create"
INSERT = "insert"
@ -383,87 +394,89 @@ const (
IMPORT = "import"
PRUNES = "prunes"
INPUTS = "inputs"
SCRIPT = "script"
INVITE = "invite"
COMMIT = "commit"
)
var Index = &ice.Context{Name: "mdb", Help: "数据模块",
Commands: map[string]*ice.Command{
INSERT: {Name: "insert conf key type arg...", Help: "添加", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
switch arg[2] {
case HASH:
_hash_insert(m, arg[0], arg[1], arg[3:]...)
case LIST:
_list_insert(m, arg[0], arg[1], arg[3:]...)
}
}},
DELETE: {Name: "delete conf key type field value", Help: "删除", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
switch arg[2] {
case HASH:
_hash_delete(m, arg[0], arg[1], arg[3], arg[4])
case LIST:
_list_delete(m, arg[0], arg[1], arg[3], arg[4])
}
}},
MODIFY: {Name: "modify conf key type field value arg...", Help: "编辑", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
switch arg[2] {
case HASH:
_hash_modify(m, arg[0], arg[1], arg[3], arg[4], arg[5:]...)
case LIST:
_list_modify(m, arg[0], arg[1], arg[3], arg[4], arg[5:]...)
}
}},
SELECT: {Name: "select conf key type field value", Help: "数据查询", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
switch arg[2] {
case HASH:
_hash_select(m, arg[0], arg[1], kit.Select("", arg, 3), kit.Select(kit.MDB_FOREACH, arg, 4))
case LIST:
_list_select(m, arg[0], arg[1], kit.Select("", arg, 3), kit.Select("", arg, 4))
case ZONE:
_zone_select(m, arg[0], arg[1], kit.Select("", arg, 3), kit.Select("", arg, 4))
}
}},
EXPORT: {Name: "export conf key type file", Help: "导出数据", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
m.Option("cache.limit", -2)
switch file := _file_name(m, arg...); arg[2] {
case HASH:
_hash_export(m, arg[0], arg[1], file)
case LIST:
_list_export(m, arg[0], arg[1], file)
case ZONE:
_zone_export(m, arg[0], arg[1], file)
}
}},
IMPORT: {Name: "import conf key type file", Help: "导入数据", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
switch file := _file_name(m, arg...); arg[2] {
case HASH:
_hash_import(m, arg[0], arg[1], file)
case LIST:
_list_import(m, arg[0], arg[1], file)
case ZONE:
_zone_import(m, arg[0], arg[1], file)
}
}},
PRUNES: {Name: "prunes conf key type [field value]...", Help: "清理数据", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
switch arg[2] {
case HASH:
_hash_prunes(m, arg[0], arg[1], arg[3:]...)
case LIST:
}
}},
INPUTS: {Name: "inputs conf key type field value", Help: "输入补全", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
switch arg[2] {
case HASH:
_hash_inputs(m, arg[0], arg[1], kit.Select("", arg, 3), kit.Select("", arg, 4))
case LIST:
}
}},
},
}
const MDB = "mdb"
var Index = &ice.Context{Name: MDB, Help: "数据模块", Commands: map[string]*ice.Command{
INSERT: {Name: "insert conf key type arg...", Help: "添加", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
switch arg[2] {
case HASH:
_hash_insert(m, arg[0], arg[1], arg[3:]...)
case LIST:
_list_insert(m, arg[0], arg[1], arg[3:]...)
}
}},
DELETE: {Name: "delete conf key type field value", Help: "删除", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
switch arg[2] {
case HASH:
_hash_delete(m, arg[0], arg[1], arg[3], arg[4])
case LIST:
_list_delete(m, arg[0], arg[1], arg[3], arg[4])
}
}},
MODIFY: {Name: "modify conf key type field value arg...", Help: "编辑", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
switch arg[2] {
case HASH:
_hash_modify(m, arg[0], arg[1], arg[3], arg[4], arg[5:]...)
case LIST:
_list_modify(m, arg[0], arg[1], arg[3], arg[4], arg[5:]...)
}
}},
SELECT: {Name: "select conf key type field value", Help: "查询", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
switch arg[2] {
case HASH:
_hash_select(m, arg[0], arg[1], kit.Select("", arg, 3), kit.Select(kit.MDB_FOREACH, arg, 4))
case LIST:
_list_select(m, arg[0], arg[1], kit.Select("", arg, 3), kit.Select("", arg, 4))
case ZONE:
_zone_select(m, arg[0], arg[1], kit.Select("", arg, 3), kit.Select("", arg, 4))
}
}},
EXPORT: {Name: "export conf key type file", Help: "导出", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
switch file := _file_name(m, arg...); arg[2] {
case HASH:
_hash_export(m, arg[0], arg[1], file)
case LIST:
_list_export(m, arg[0], arg[1], file)
case ZONE:
_zone_export(m, arg[0], arg[1], file)
}
}},
IMPORT: {Name: "import conf key type file", Help: "导入", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
switch file := _file_name(m, arg...); arg[2] {
case HASH:
_hash_import(m, arg[0], arg[1], file)
case LIST:
_list_import(m, arg[0], arg[1], file)
case ZONE:
_zone_import(m, arg[0], arg[1], file)
}
}},
PRUNES: {Name: "prunes conf key type [field value]...", Help: "清理", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
switch arg[2] {
case HASH:
_hash_prunes(m, arg[0], arg[1], arg[3:]...)
case LIST:
_list_prunes(m, arg[0], arg[1], arg[3:]...)
}
}},
INPUTS: {Name: "inputs conf key type field value", Help: "补全", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
switch arg[2] {
case HASH:
_hash_inputs(m, arg[0], arg[1], kit.Select("name", arg, 3), kit.Select("", arg, 4))
case LIST:
_hash_inputs(m, arg[0], arg[1], kit.Select("name", arg, 3), kit.Select("", arg, 4))
}
}},
}}
func init() {
ice.Index.Register(Index, nil,
INSERT, DELETE, MODIFY, SELECT,
EXPORT, IMPORT, PRUNES, INPUTS,
PLUGIN, RENDER, SEARCH, ENGINE,
PLUGIN, RENDER, ENGINE, SEARCH,
)
}

View File

@ -14,7 +14,7 @@ func init() {
},
Commands: map[string]*ice.Command{
PLUGIN: {Name: "plugin type name text", Help: "插件", Action: map[string]*ice.Action{
CREATE: {Name: "create type [cmd [ctx]]", Help: "创建", Hand: func(m *ice.Message, arg ...string) {
CREATE: {Name: "create type cmd ctx", Help: "创建", Hand: func(m *ice.Message, arg ...string) {
m.Rich(PLUGIN, nil, kit.Dict(kit.MDB_TYPE, arg[0], kit.MDB_NAME, kit.Select(arg[0], arg, 1), kit.MDB_TEXT, kit.Select("", arg, 2)))
}},
}, Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {

View File

@ -13,8 +13,8 @@ func init() {
RENDER: {Name: "render", Help: "渲染", Value: kit.Data(kit.MDB_SHORT, kit.MDB_TYPE)},
},
Commands: map[string]*ice.Command{
RENDER: {Name: "render type name [text]", Help: "渲染", Action: map[string]*ice.Action{
CREATE: {Name: "create type [cmd [ctx]]", Help: "创建", Hand: func(m *ice.Message, arg ...string) {
RENDER: {Name: "render type name text", Help: "渲染", Action: map[string]*ice.Action{
CREATE: {Name: "create type cmd ctx", Help: "创建", Hand: func(m *ice.Message, arg ...string) {
m.Rich(RENDER, nil, kit.Dict(kit.MDB_TYPE, arg[0], kit.MDB_NAME, kit.Select(arg[0], arg, 1), kit.MDB_TEXT, kit.Select("", arg, 2)))
}},
}, Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {

View File

@ -15,8 +15,8 @@ func init() {
SEARCH: {Name: "search", Help: "搜索", Value: kit.Data(kit.MDB_SHORT, kit.MDB_TYPE)},
},
Commands: map[string]*ice.Command{
SEARCH: {Name: "search type word [text]", Help: "搜索", Action: map[string]*ice.Action{
CREATE: {Name: "create type [cmd [ctx]]", Help: "创建", Hand: func(m *ice.Message, arg ...string) {
SEARCH: {Name: "search type word text", Help: "搜索", Action: map[string]*ice.Action{
CREATE: {Name: "create type cmd ctx", Help: "创建", Hand: func(m *ice.Message, arg ...string) {
m.Rich(SEARCH, nil, kit.Dict(kit.MDB_TYPE, arg[0], kit.MDB_NAME, kit.Select(arg[0], arg, 1), kit.MDB_TEXT, kit.Select("", arg, 2)))
}},
}, Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {

View File

@ -14,12 +14,7 @@ import (
"strings"
)
type Winsize struct {
Height uint16
Width uint16
x uint16
y uint16
}
type Winsize struct{ Height, Width, x, y uint16 }
func _ssh_exec(m *ice.Message, cmd string, arg []string, env []string, tty io.ReadWriter, done func()) {
m.Log_IMPORT(CMD, cmd, ARG, arg, ENV, env)
@ -58,7 +53,7 @@ func _ssh_watch(m *ice.Message, meta map[string]string, h string, input io.Reade
case '\r', '\n':
cmd := strings.TrimSpace(string(buf[:i]))
m.Log_IMPORT(aaa.HOSTNAME, meta[aaa.HOSTNAME], aaa.USERNAME, meta[aaa.USERNAME], CMD, cmd)
m.Cmdy(mdb.INSERT, CHANNEL, kit.Keys(kit.MDB_HASH, h), mdb.LIST, CMD, cmd)
m.Cmdy(mdb.INSERT, CHANNEL, kit.Keys(kit.MDB_HASH, h), mdb.LIST, kit.MDB_TYPE, CMD, kit.MDB_TEXT, cmd)
i = 0
default:
if i += n; i >= 4096 {
@ -83,12 +78,12 @@ func init() {
}},
}, Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
if len(arg) == 0 {
m.Option(mdb.FIELDS, "time,hash,status,tty,count")
m.Option(mdb.FIELDS, "time,hash,status,username,hostname,hostport,tty,count")
m.Cmdy(mdb.SELECT, CHANNEL, "", mdb.HASH)
return
}
m.Option(mdb.FIELDS, kit.Select("time,id,cmd", mdb.DETAIL, len(arg) > 1))
m.Option(mdb.FIELDS, kit.Select("time,id,type,text", mdb.DETAIL, len(arg) > 1))
m.Cmdy(mdb.SELECT, CHANNEL, kit.Keys(kit.MDB_HASH, arg[0]), mdb.LIST, kit.MDB_ID, arg[1:])
}},
},

View File

@ -15,7 +15,7 @@ import (
"golang.org/x/crypto/ssh"
)
func _ssh_conn(m *ice.Message, conn net.Conn, hostport, username string) (*ssh.Client, error) {
func _ssh_conn(m *ice.Message, conn net.Conn, username, hostport string) (*ssh.Client, error) {
key, e := ssh.ParsePrivateKey([]byte(m.Cmdx(nfs.CAT, path.Join(os.Getenv("HOME"), m.Option("private")))))
m.Assert(e)
@ -46,9 +46,8 @@ func init() {
CONNECT: {Name: "connect hash auto 添加 清理", Help: "连接", Action: map[string]*ice.Action{
tcp.DIAL: {Name: "dial username=shy host=shylinux.com port=22 private=.ssh/id_rsa", Help: "添加", Hand: func(m *ice.Message, arg ...string) {
m.Option(tcp.DIAL_CB, func(c net.Conn) {
client, e := _ssh_conn(m, c,
kit.Select(m.Option(tcp.HOST), "shylinux.com")+":"+kit.Select("22", m.Option(tcp.PORT)),
kit.Select("shy", m.Option(aaa.USERNAME)),
client, e := _ssh_conn(m, c, kit.Select("shy", m.Option(aaa.USERNAME)),
kit.Select("shylinux.com", m.Option(tcp.HOST))+":"+kit.Select("22", m.Option(tcp.PORT)),
)
m.Assert(e)
@ -60,9 +59,11 @@ func init() {
CONNECT, client,
))
m.Cmd(CONNECT, SESSION, kit.MDB_HASH, h)
m.Echo(h)
})
m.Cmds(tcp.CLIENT, tcp.DIAL, arg)
m.Sleep("100ms")
}},
SESSION: {Name: "session hash", Help: "会话", Hand: func(m *ice.Message, arg ...string) {
m.Richs(CONNECT, "", m.Option(kit.MDB_HASH), func(key string, value map[string]interface{}) {

View File

@ -13,21 +13,26 @@ import (
"encoding/base64"
"errors"
"fmt"
"github.com/kr/pty"
"io"
"net"
"os"
"path"
"strings"
"github.com/kr/pty"
)
func _ssh_meta(conn ssh.ConnMetadata) map[string]string {
return map[string]string{aaa.USERNAME: conn.User(), aaa.HOSTPORT: conn.RemoteAddr().String()}
}
func _ssh_config(m *ice.Message, h string) *ssh.ServerConfig {
config := &ssh.ServerConfig{
PublicKeyCallback: func(conn ssh.ConnMetadata, key ssh.PublicKey) (*ssh.Permissions, error) {
meta, err := map[string]string{aaa.USERNAME: conn.User()}, errors.New(ice.ErrNotAuth)
meta, err := _ssh_meta(conn), errors.New(ice.ErrNotAuth)
if tcp.IsLocalHost(m, strings.Split(conn.RemoteAddr().String(), ":")[0]) {
m.Log_AUTH(aaa.HOSTPORT, conn.RemoteAddr(), aaa.USERNAME, conn.User())
err = nil
err = nil // 本机用户
} else {
m.Cmd(mdb.SELECT, SERVICE, kit.Keys(kit.MDB_HASH, h), mdb.LIST).Table(func(index int, value map[string]string, head []string) {
if !strings.HasPrefix(value[kit.MDB_NAME], conn.User()+"@") {
@ -38,8 +43,8 @@ func _ssh_config(m *ice.Message, h string) *ssh.ServerConfig {
if bytes.Compare(pub.Marshal(), key.Marshal()) == 0 {
m.Log_AUTH(aaa.HOSTPORT, conn.RemoteAddr(), aaa.USERNAME, conn.User(), aaa.HOSTNAME, value[kit.MDB_NAME])
meta[aaa.USERNAME] = value[kit.MDB_NAME]
err = nil
meta[aaa.HOSTNAME] = kit.Select("", kit.Split(value[kit.MDB_NAME], "@"), 1)
err = nil // 认证成功
}
}
}
@ -48,11 +53,11 @@ func _ssh_config(m *ice.Message, h string) *ssh.ServerConfig {
return &ssh.Permissions{Extensions: meta}, err
},
PasswordCallback: func(conn ssh.ConnMetadata, password []byte) (*ssh.Permissions, error) {
meta, err := map[string]string{aaa.USERNAME: conn.User()}, errors.New(ice.ErrNotAuth)
meta, err := _ssh_meta(conn), errors.New(ice.ErrNotAuth)
m.Richs(aaa.USER, "", conn.User(), func(k string, value map[string]interface{}) {
if string(password) == kit.Format(value[aaa.PASSWORD]) {
m.Log_AUTH(aaa.HOSTPORT, conn.RemoteAddr(), aaa.USERNAME, conn.User(), aaa.PASSWORD, strings.Repeat("*", len(kit.Format(value[aaa.PASSWORD]))))
err = nil
err = nil // 密码登录
}
})
return &ssh.Permissions{Extensions: meta}, err
@ -101,7 +106,7 @@ func _ssh_handle(m *ice.Message, meta map[string]string, c net.Conn, channel ssh
}
defer tty.Close()
h := m.Rich(CHANNEL, "", kit.Data(kit.MDB_STATUS, tcp.OPEN, TTY, tty.Name(), aaa.HOSTPORT, c.RemoteAddr().String()))
h := m.Rich(CHANNEL, "", kit.Data(kit.MDB_STATUS, tcp.OPEN, TTY, tty.Name(), meta))
meta[CHANNEL] = h
for request := range requests {
@ -150,20 +155,32 @@ func init() {
SERVICE: {Name: SERVICE, Help: "服务", Value: kit.Data(
"welcome", "\r\nwelcome to context world\r\n",
"goodbye", "\r\ngoodbye of context world\r\n",
kit.MDB_SHORT, tcp.PORT,
)},
},
Commands: map[string]*ice.Command{
SERVICE: {Name: "service hash id auto 监听 清理", Help: "服务", Action: map[string]*ice.Action{
tcp.LISTEN: {Name: "listen port=9030 private=.ssh/id_rsa", Help: "监听", Hand: func(m *ice.Message, arg ...string) {
h := m.Cmdx(mdb.INSERT, SERVICE, "", mdb.HASH, kit.MDB_STATUS, tcp.OPEN, arg)
SERVICE: {Name: "service port id auto 监听 清理", Help: "服务", Action: map[string]*ice.Action{
tcp.LISTEN: {Name: "listen port=9030 private=.ssh/id_rsa auth=.ssh/authorized_keys", Help: "监听", Hand: func(m *ice.Message, arg ...string) {
if m.Richs(SERVICE, "", m.Option(tcp.PORT), func(key string, value map[string]interface{}) {
kit.Value(value, "meta.status", tcp.OPEN)
}) == nil {
m.Cmd(mdb.INSERT, SERVICE, "", mdb.HASH, kit.MDB_STATUS, tcp.OPEN,
tcp.PORT, m.Option(tcp.PORT), "private", m.Option("private"), "auth", m.Option("auth"), arg)
m.Cmd(SERVICE, mdb.IMPORT, kit.MDB_FILE, m.Option("auth"))
}
m.Option(tcp.LISTEN_CB, func(c net.Conn) { m.Go(func() { _ssh_accept(m, h, c) }) })
m.Option(tcp.LISTEN_CB, func(c net.Conn) { m.Go(func() { _ssh_accept(m, kit.Hashs(m.Option(tcp.PORT)), c) }) })
m.Go(func() { m.Cmdy(tcp.SERVER, tcp.LISTEN, kit.MDB_NAME, SSH, tcp.PORT, m.Option(tcp.PORT)) })
}},
mdb.INSERT: {Name: "insert text:textarea", Help: "添加", Hand: func(m *ice.Message, arg ...string) {
ls := kit.Split(m.Option(kit.MDB_TEXT))
m.Cmdy(mdb.INSERT, SERVICE, kit.Keys(kit.MDB_HASH, kit.Hashs(m.Option(tcp.PORT))), mdb.LIST,
kit.MDB_TYPE, ls[0], kit.MDB_NAME, ls[len(ls)-1], kit.MDB_TEXT, strings.Join(ls[1:len(ls)-1], "+"))
}},
mdb.EXPORT: {Name: "export file=.ssh/authorized_keys", Help: "导出", Hand: func(m *ice.Message, arg ...string) {
list := []string{}
m.Cmd(mdb.SELECT, SERVICE, kit.Keys(kit.MDB_HASH, m.Option(kit.MDB_HASH)), mdb.LIST).Table(func(index int, value map[string]string, head []string) {
m.Cmd(mdb.SELECT, SERVICE, kit.Keys(kit.MDB_HASH, kit.Hashs(m.Option(tcp.PORT))), mdb.LIST).Table(func(index int, value map[string]string, head []string) {
list = append(list, fmt.Sprintf("%s %s %s", value[kit.MDB_TYPE], value[kit.MDB_TEXT], value[kit.MDB_NAME]))
})
@ -175,7 +192,7 @@ func init() {
p := path.Join(os.Getenv("HOME"), m.Option(kit.MDB_FILE))
for _, pub := range strings.Split(m.Cmdx(nfs.CAT, p), "\n") {
if ls := kit.Split(pub); len(pub) > 10 {
m.Cmd(mdb.INSERT, SERVICE, kit.Keys(kit.MDB_HASH, m.Option(kit.MDB_HASH)), mdb.LIST,
m.Cmd(mdb.INSERT, SERVICE, kit.Keys(kit.MDB_HASH, kit.Hashs(m.Option(tcp.PORT))), mdb.LIST,
kit.MDB_TYPE, ls[0], kit.MDB_NAME, ls[len(ls)-1], kit.MDB_TEXT, strings.Join(ls[1:len(ls)-1], "+"))
}
}
@ -186,14 +203,14 @@ func init() {
}},
}, Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
if len(arg) == 0 {
m.Option(mdb.FIELDS, "time,hash,status,port,private,count")
m.Cmdy(mdb.SELECT, SERVICE, "", mdb.HASH, kit.MDB_HASH, arg)
m.PushAction("导入")
m.Option(mdb.FIELDS, "time,status,port,private,auth,count")
m.Cmdy(mdb.SELECT, SERVICE, "", mdb.HASH)
m.PushAction("导入,添加,导出")
return
}
m.Option(mdb.FIELDS, kit.Select("time,id,type,name,text", mdb.DETAIL, len(arg) > 1))
m.Cmdy(mdb.SELECT, SERVICE, kit.Keys(kit.MDB_HASH, arg[0]), mdb.LIST, kit.MDB_ID, arg[1:])
m.Cmdy(mdb.SELECT, SERVICE, kit.Keys(kit.MDB_HASH, kit.Hashs(arg[0])), mdb.LIST, kit.MDB_ID, arg[1:])
}},
},
}, nil)

View File

@ -34,8 +34,7 @@ var Index = &ice.Context{Name: SSH, Help: "终端模块", Commands: map[string]*
func init() {
ice.Index.Register(Index, &Frame{},
CONNECT, SESSION, SERVICE, CHANNEL,
SOURCE, TARGET, PROMPT, RETURN,
CONNECT, SESSION,
SERVICE, CHANNEL,
)
}

View File

@ -9,11 +9,3 @@ field "服务" ssh.service
field "通道" ssh.channel
field "连接" ssh.connect
field "会话" ssh.session
return
chapter "应用"
field "公钥" ssh.public
field "服务" ssh.listen
field "命令" ssh.command

View File

@ -1,94 +0,0 @@
package tcp
import (
ice "github.com/shylinux/icebergs"
"github.com/shylinux/icebergs/base/aaa"
"github.com/shylinux/icebergs/base/cli"
"bufio"
"net"
"net/url"
"strings"
)
func init() {
Index.Merge(&ice.Context{
Commands: map[string]*ice.Command{
"server": {Name: "server [tcp4|tcp6|udp4|udp6] addr", Help: "server", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
proto := "tcp4"
switch arg[0] {
case "tcp", "tcp4", "tcp6", "udp", "udp4", "udp6", "ip", "ip4", "ip6":
proto, arg = arg[0], arg[1:]
}
if l, e := net.Listen(proto, arg[0]); m.Assert(e) {
m.Gos(m, func(m *ice.Message) {
// 启动服务
m.Logs(ice.LOG_LISTEN, "addr", l.Addr())
for {
if c, e := l.Accept(); m.Assert(e) {
m.Gos(m.Spawns(), func(msg *ice.Message) {
// 建立连接
msg.Logs(ice.LOG_ACCEPT, "addr", c.RemoteAddr())
msg.Option(ice.MSG_USERADDR, c.RemoteAddr())
msg.Option(ice.MSG_USERNAME, "")
msg.Option(ice.MSG_USERROLE, "")
switch msg.Cmdx("check", c.RemoteAddr().String()) {
case "local":
// 本机用户
msg.Option(ice.MSG_USERNAME, msg.Conf(cli.RUNTIME, "boot.username"))
msg.Option(ice.MSG_USERROLE, msg.Cmdx(aaa.ROLE, "check", msg.Option(ice.MSG_USERNAME)))
msg.Logs(ice.LOG_AUTH, "name", msg.Option(ice.MSG_USERNAME), "role", msg.Option(ice.MSG_USERROLE))
}
cmds := []string{}
buf := bufio.NewWriter(c)
for bio := bufio.NewScanner(c); bio.Scan(); {
text := bio.Text()
msg.Logs("scan", "len", len(text), "text", text)
if len(text) == 0 {
if len(cmds) > 0 {
msg.Cmd(aaa.ROLE, "right")
// 执行命令
res := msg.Cmd(cmds)
// 返回结果
for _, str := range res.Resultv() {
buf.WriteString("result:")
buf.WriteString(url.QueryEscape(str))
buf.WriteString("\n")
}
buf.WriteString("\n")
buf.Flush()
cmds = cmds[:0]
}
continue
}
// 解析请求
line := strings.SplitN(bio.Text(), ":", 2)
line[0], e = url.QueryUnescape(line[0])
m.Assert(e)
line[1], e = url.QueryUnescape(line[1])
m.Assert(e)
switch line[0] {
case "cmds", ice.MSG_DETAIL:
cmds = append(cmds, line[1])
default:
msg.Option(line[0], line[1])
}
}
msg.Logs(ice.LOG_FINISH, "addr", c.RemoteAddr())
})
}
}
m.Logs(ice.LOG_FINISH, "addr", l.Addr())
})
}
}},
},
}, nil)
}

View File

@ -8,6 +8,40 @@ import (
"net"
)
type Stat struct {
nc, nr, nw int
}
type Conn struct {
m *ice.Message
h string
s *Stat
net.Conn
}
func (c *Conn) Read(b []byte) (int, error) {
n, e := c.Conn.Read(b)
c.s.nr += n
c.m.Conf(CLIENT, kit.Keys(kit.MDB_HASH, c.h, kit.MDB_META, "nread"), c.s.nr)
return n, e
}
func (c *Conn) Write(b []byte) (int, error) {
n, e := c.Conn.Write(b)
c.s.nw += n
c.m.Conf(CLIENT, kit.Keys(kit.MDB_HASH, c.h, kit.MDB_META, "nwrite"), c.s.nw)
return n, e
}
func (c *Conn) Close() error {
c.m.Cmd(mdb.MODIFY, CLIENT, "", mdb.HASH, kit.MDB_HASH, c.h, kit.MDB_STATUS, CLOSE, "nread", c.s.nr, "nwrite", c.s.nw)
return c.Conn.Close()
}
const (
OPEN = "open"
CLOSE = "close"
ERROR = "error"
)
const (
DIAL_CB = "dial.cb"
DIAL = "dial"
@ -22,12 +56,15 @@ func init() {
},
Commands: map[string]*ice.Command{
CLIENT: {Name: "client hash auto 连接 清理", Help: "客户端", Action: map[string]*ice.Action{
DIAL: {Name: "dial host=localhost port=9010", Help: "连接", Hand: func(m *ice.Message, arg ...string) {
DIAL: {Name: "dial port=9010 host=", Help: "连接", Hand: func(m *ice.Message, arg ...string) {
c, e := net.Dial(TCP, m.Option(HOST)+":"+m.Option(PORT))
h := m.Cmdx(mdb.INSERT, CLIENT, "", mdb.HASH, HOST, m.Option(HOST), PORT, m.Option(PORT),
kit.MDB_NAME, m.Option(kit.MDB_NAME), kit.MDB_STATUS, kit.Select(ERROR, OPEN, e == nil), kit.MDB_ERROR, kit.Format(e))
h := m.Option(kit.MDB_HASH)
if h == "" {
h = m.Cmdx(mdb.INSERT, CLIENT, "", mdb.HASH, HOST, m.Option(HOST), PORT, m.Option(PORT),
kit.MDB_NAME, m.Option(kit.MDB_NAME), kit.MDB_STATUS, kit.Select(ERROR, OPEN, e == nil), kit.MDB_ERROR, kit.Format(e))
}
c = &Conn{h: h, m: m, s: &Stat{}, Conn: c}
c = &Conn{m: m, h: h, s: &Stat{}, Conn: c}
if e == nil {
defer c.Close()
}
@ -58,7 +95,7 @@ func init() {
m.Cmdy(mdb.PRUNES, CLIENT, "", mdb.HASH, kit.MDB_STATUS, CLOSE)
}},
}, Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
m.Option(mdb.FIELDS, kit.Select(mdb.DETAIL, "time,hash,status,name,host,port,error,nread,nwrite", len(arg) == 0))
m.Option(mdb.FIELDS, kit.Select("time,hash,status,name,host,port,error,nread,nwrite", mdb.DETAIL, len(arg) > 0))
m.Cmdy(mdb.SELECT, CLIENT, "", mdb.HASH, kit.MDB_HASH, arg)
m.PushAction("删除")
}},

View File

@ -66,17 +66,17 @@ func init() {
Index.Merge(&ice.Context{
Configs: map[string]*ice.Config{
HOST: {Name: HOST, Help: "主机", Value: kit.Data(
aaa.Black, kit.Dict(kit.MDB_SHORT, kit.MDB_TEXT),
aaa.Black, kit.Data(kit.MDB_SHORT, kit.MDB_TEXT),
aaa.White, kit.Data(kit.MDB_SHORT, kit.MDB_TEXT),
)},
},
Commands: map[string]*ice.Command{
HOST: {Name: "host name auto", Help: "主机", Action: map[string]*ice.Action{
aaa.White: {Name: "white", Help: "白名单", Hand: func(m *ice.Message, arg ...string) {
m.Rich(HOST, kit.Keys("meta.white"), kit.Dict(kit.MDB_NAME, "", kit.MDB_TEXT, arg[0]))
}},
aaa.Black: {Name: "black", Help: "黑名单", Hand: func(m *ice.Message, arg ...string) {
m.Rich(HOST, kit.Keys("meta.black"), kit.Dict(kit.MDB_NAME, "", kit.MDB_TEXT, arg[0]))
m.Rich(HOST, kit.Keys("meta.black"), kit.Dict(kit.MDB_TEXT, arg[0]))
}},
aaa.White: {Name: "white", Help: "白名单", Hand: func(m *ice.Message, arg ...string) {
m.Rich(HOST, kit.Keys("meta.white"), kit.Dict(kit.MDB_TEXT, arg[0]))
}},
}, Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
_host_list(m, kit.Select("", arg, 0))

View File

@ -27,7 +27,7 @@ func _port_right(m *ice.Message, begin string) string {
}
for i := current; i < end; i++ {
if c, e := net.Dial("tcp", kit.Format(":%d", i)); e == nil {
if c, e := net.Dial(TCP, kit.Format(":%d", i)); e == nil {
m.Info("port exists %v", i)
defer c.Close()
continue

View File

@ -9,38 +9,9 @@ import (
"strings"
)
type Stat struct {
nc, nr, nw int
}
type Conn struct {
h string
m *ice.Message
s *Stat
net.Conn
}
func (c *Conn) Read(b []byte) (int, error) {
n, e := c.Conn.Read(b)
c.s.nr += n
c.m.Conf(CLIENT, kit.Keys(kit.MDB_HASH, c.h, kit.MDB_META, "nwrite"), c.s.nw)
return n, e
}
func (c *Conn) Write(b []byte) (int, error) {
n, e := c.Conn.Write(b)
c.s.nw += n
c.m.Conf(CLIENT, kit.Keys(kit.MDB_HASH, c.h, kit.MDB_META, "nread"), c.s.nr)
return n, e
}
func (c *Conn) Close() error {
c.m.Cmd(mdb.MODIFY, CLIENT, "", mdb.HASH, kit.MDB_HASH, c.h, kit.MDB_STATUS, CLOSE, "nread", c.s.nr, "nwrite", c.s.nw)
return c.Conn.Close()
}
type Listener struct {
h string
m *ice.Message
h string
s *Stat
net.Listener
@ -58,19 +29,13 @@ func (l Listener) Accept() (net.Conn, error) {
h := l.m.Cmdx(mdb.INSERT, CLIENT, "", mdb.HASH, HOST, ls[0], PORT, ls[1],
kit.MDB_NAME, l.m.Option(kit.MDB_NAME), kit.MDB_STATUS, kit.Select(ERROR, OPEN, e == nil), kit.MDB_ERROR, kit.Format(e))
c = &Conn{h: h, m: l.m, s: &Stat{}, Conn: c}
return c, e
return &Conn{m: l.m, h: h, s: &Stat{}, Conn: c}, e
}
func (l Listener) Close() error {
l.m.Cmd(mdb.MODIFY, SERVER, "", mdb.HASH, kit.MDB_HASH, l.h, kit.MDB_STATUS, CLOSE)
return l.Listener.Close()
}
const (
OPEN = "open"
CLOSE = "close"
ERROR = "error"
)
const (
LISTEN_CB = "listen.cb"
LISTEN = "listen"
@ -85,14 +50,14 @@ func init() {
},
Commands: map[string]*ice.Command{
SERVER: {Name: "server hash auto 监听 清理", Help: "服务器", Action: map[string]*ice.Action{
LISTEN: {Name: "LISTEN host=localhost port=9010", Help: "监听", Hand: func(m *ice.Message, arg ...string) {
LISTEN: {Name: "LISTEN host= port=9010", Help: "监听", Hand: func(m *ice.Message, arg ...string) {
l, e := net.Listen(TCP, m.Option(HOST)+":"+m.Option(PORT))
h := m.Option(kit.MDB_HASH)
if h == "" {
h = m.Cmdx(mdb.INSERT, SERVER, "", mdb.HASH, kit.MDB_NAME, m.Option(kit.MDB_NAME), HOST, m.Option(HOST), PORT, m.Option(PORT), kit.MDB_STATUS, kit.Select(ERROR, OPEN, e == nil), kit.MDB_ERROR, kit.Format(e))
}
l = &Listener{h: h, m: m, s: &Stat{}, Listener: l}
l = &Listener{m: m, h: h, s: &Stat{}, Listener: l}
if e == nil {
defer l.Close()
}
@ -121,15 +86,15 @@ func init() {
default:
for {
c, e := l.Accept()
if e == nil {
b := make([]byte, 1024)
if n, e := c.Read(b); e == nil {
m.Info("nonce", string(b[:n]))
c.Write(b[:n])
}
} else {
if e != nil {
break
}
b := make([]byte, 4096)
if n, e := c.Read(b); e == nil {
m.Info("nonce", string(b[:n]))
c.Write(b[:n])
}
c.Close()
}
}
@ -142,7 +107,7 @@ func init() {
m.Cmdy(mdb.PRUNES, SERVER, "", mdb.HASH, kit.MDB_STATUS, CLOSE)
}},
}, Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
m.Option(mdb.FIELDS, kit.Select(mdb.DETAIL, "time,hash,status,name,host,port,error,nconn", len(arg) == 0))
m.Option(mdb.FIELDS, kit.Select("time,hash,status,name,host,port,error,nconn", mdb.DETAIL, len(arg) > 0))
m.Cmdy(mdb.SELECT, SERVER, "", mdb.HASH, kit.MDB_HASH, arg)
m.PushAction("删除")
}},

View File

@ -18,16 +18,10 @@ var Index = &ice.Context{Name: TCP, Help: "通信模块",
}},
ice.CTX_EXIT: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
m.Richs(CLIENT, "", kit.MDB_FOREACH, func(key string, value map[string]interface{}) {
if value[kit.MDB_META] != nil {
value = value[kit.MDB_META].(map[string]interface{})
}
kit.Value(value, "status", CLOSE)
kit.Value(value, "meta.status", CLOSE)
})
m.Richs(SERVER, "", kit.MDB_FOREACH, func(key string, value map[string]interface{}) {
if value[kit.MDB_META] != nil {
value = value[kit.MDB_META].(map[string]interface{})
}
kit.Value(value, "status", CLOSE)
kit.Value(value, "meta.status", CLOSE)
})
m.Save()
}},

47
data.go
View File

@ -5,49 +5,46 @@ import (
"github.com/shylinux/toolkits/miss"
)
func (m *Message) Richs(key string, chain interface{}, raw interface{}, cb interface{}) (res map[string]interface{}) {
cache := m.Confm(key, chain)
func (m *Message) Richs(prefix string, chain interface{}, raw interface{}, cb interface{}) (res map[string]interface{}) {
cache := m.Confm(prefix, chain)
if cache == nil {
return nil
}
return miss.Richs(kit.Keys(key, chain), cache, raw, cb)
return miss.Richs(kit.Keys(prefix, chain), cache, raw, cb)
}
func (m *Message) Rich(key string, chain interface{}, data interface{}) string {
cache := m.Confm(key, chain)
func (m *Message) Rich(prefix string, chain interface{}, data interface{}) string {
cache := m.Confm(prefix, chain)
if cache == nil {
cache = map[string]interface{}{}
m.Confv(key, chain, cache)
cache = kit.Data()
m.Confv(prefix, chain, cache)
}
return miss.Rich(kit.Keys(key, chain), cache, data)
return miss.Rich(kit.Keys(prefix, chain), cache, data)
}
func (m *Message) Grow(key string, chain interface{}, data interface{}) int {
cache := m.Confm(key, chain)
func (m *Message) Grow(prefix string, chain interface{}, data interface{}) int {
cache := m.Confm(prefix, chain)
if cache == nil {
cache = map[string]interface{}{}
m.Confv(key, chain, cache)
cache = kit.Data()
m.Confv(prefix, chain, cache)
}
return miss.Grow(kit.Keys(key, chain), cache, data)
return miss.Grow(kit.Keys(prefix, chain), cache, data)
}
func (m *Message) Grows(key string, chain interface{}, match string, value string, cb interface{}) map[string]interface{} {
cache := m.Confm(key, chain)
func (m *Message) Grows(prefix string, chain interface{}, match string, value string, cb interface{}) map[string]interface{} {
cache := m.Confm(prefix, chain)
if cache == nil {
return nil
}
begin := kit.Int(m.Option("cache.begin"))
limit := kit.Int(m.Option("cache.limit"))
count := kit.Int(m.Option("cache.count", kit.Int(kit.Value(cache, "meta.count"))))
if limit == -2 {
} else if limit == -1 {
} else if begin >= 0 || m.Option("cache.limit") == "" {
if begin := kit.Int(m.Option("cache.begin")); begin != 0 && limit > 0 {
count := kit.Int(m.Option("cache.count", kit.Int(kit.Value(cache, "meta.count"))))
if begin > 0 {
begin -= 1
m.Option("cache.offend", count-begin-limit)
} else {
m.Option("cache.offend", -begin-limit)
}
m.Option("cache.offend", count-begin-limit)
} else {
m.Option("cache.offend", -begin-limit)
}
return miss.Grows(kit.Keys(key, chain), cache,
return miss.Grows(kit.Keys(prefix, chain), cache,
kit.Int(kit.Select("0", m.Option("cache.offend"))),
kit.Int(kit.Select("10", m.Option("cache.limit"))),
match, value, cb)

View File

@ -201,7 +201,7 @@ var Index = &ice.Context{Name: TMUX, Help: "工作台",
m.Cmdy(mdb.SELECT, SCRIPT, "", mdb.HASH)
}},
mdb.SCRIPT: {Name: "script name", Help: "脚本", Hand: func(m *ice.Message, arg ...string) {
"script": {Name: "script name", Help: "脚本", Hand: func(m *ice.Message, arg ...string) {
m.Cmd(mdb.SELECT, SCRIPT, "", mdb.HASH, kit.MDB_NAME, m.Option(kit.MDB_NAME)).Table(func(index int, value map[string]string, head []string) {
switch value[kit.MDB_TYPE] {
case "shell":