1
0
mirror of https://shylinux.com/x/icebergs synced 2025-04-28 18:22:02 +08:00

opt ssh.connect

This commit is contained in:
shaoying 2021-06-01 01:09:52 +08:00
parent fbe99a51bd
commit 122c3295ff
15 changed files with 211 additions and 247 deletions

View File

@ -85,7 +85,7 @@ func init() {
m.Push("code", _totp_get(value[SECRET], kit.Int(value[NUMBER]), period)) m.Push("code", _totp_get(value[SECRET], kit.Int(value[NUMBER]), period))
if len(arg) > 0 { if len(arg) > 0 {
m.PushQRCode("show", kit.Format(m.Conf(TOTP, kit.Keym(kit.MDB_LINK)), value[kit.MDB_NAME], value[SECRET])) m.PushQRCode("scan", kit.Format(m.Conf(TOTP, kit.Keym(kit.MDB_LINK)), value[kit.MDB_NAME], value[SECRET]))
m.Echo(_totp_get(value[SECRET], kit.Int(value[NUMBER]), kit.Int64(value[PERIOD]))) m.Echo(_totp_get(value[SECRET], kit.Int(value[NUMBER]), kit.Int64(value[PERIOD])))
} }
}) })

View File

@ -13,12 +13,33 @@ import (
func NodeInfo(m *ice.Message, kind, name string) { func NodeInfo(m *ice.Message, kind, name string) {
name = strings.ReplaceAll(name, ".", "_") name = strings.ReplaceAll(name, ".", "_")
m.Conf(RUNTIME, "node.type", kind) m.Conf(RUNTIME, kit.Keys(NODE, kit.MDB_TYPE), kind)
m.Conf(RUNTIME, "node.name", name) m.Conf(RUNTIME, kit.Keys(NODE, kit.MDB_NAME), name)
ice.Info.NodeName = name ice.Info.NodeName = name
ice.Info.NodeType = kind ice.Info.NodeType = kind
} }
const (
MAKE = "make"
CONF = "conf"
HOST = "host"
BOOT = "boot"
NODE = "node"
)
const (
HOSTNAME = "hostname"
PATHNAME = "pathname"
USERNAME = "username"
)
const (
CTX_SELF = "ctx_self"
CTX_DEV = "ctx_dev"
CTX_SHY = "ctx_shy"
CTX_PID = "ctx_pid"
CTX_USER = "ctx_user"
CTX_SHARE = "ctx_share"
CTX_RIVER = "ctx_river"
)
const CLI = "cli" const CLI = "cli"
var Index = &ice.Context{Name: CLI, Help: "命令模块", var Index = &ice.Context{Name: CLI, Help: "命令模块",
@ -27,18 +48,18 @@ var Index = &ice.Context{Name: CLI, Help: "命令模块",
m.Load() m.Load()
// 启动配置 // 启动配置
for _, k := range []string{"ctx_self", "ctx_dev", "ctx_shy", "ctx_pid", "ctx_user", "ctx_share", "ctx_river"} { for _, k := range []string{CTX_SELF, CTX_DEV, CTX_SHY, CTX_PID, CTX_USER, CTX_SHARE, CTX_RIVER} {
m.Conf(RUNTIME, kit.Keys("conf", k), os.Getenv(k)) m.Conf(RUNTIME, kit.Keys(CONF, k), os.Getenv(k))
} }
// 主机信息 // 主机信息
m.Conf(RUNTIME, "host.GOARCH", runtime.GOARCH) m.Conf(RUNTIME, kit.Keys(HOST, "GOARCH"), runtime.GOARCH)
m.Conf(RUNTIME, "host.GOOS", runtime.GOOS) m.Conf(RUNTIME, kit.Keys(HOST, "GOOS"), runtime.GOOS)
m.Conf(RUNTIME, "host.pid", os.Getpid()) m.Conf(RUNTIME, kit.Keys(HOST, "pid"), os.Getpid())
// 启动信息 // 启动信息
if name, e := os.Hostname(); e == nil { if name, e := os.Hostname(); e == nil {
m.Conf(RUNTIME, "boot.hostname", kit.Select(name, os.Getenv("HOSTNAME"))) m.Conf(RUNTIME, kit.Keys(BOOT, HOSTNAME), kit.Select(name, os.Getenv("HOSTNAME")))
} }
if name, e := os.Getwd(); e == nil { if name, e := os.Getwd(); e == nil {
name = path.Base(kit.Select(name, os.Getenv("PWD"))) name = path.Base(kit.Select(name, os.Getenv("PWD")))
@ -46,36 +67,36 @@ var Index = &ice.Context{Name: CLI, Help: "命令模块",
name = ls[len(ls)-1] name = ls[len(ls)-1]
ls = strings.Split(name, "\\") ls = strings.Split(name, "\\")
name = ls[len(ls)-1] name = ls[len(ls)-1]
m.Conf(RUNTIME, "boot.pathname", name) m.Conf(RUNTIME, kit.Keys(BOOT, PATHNAME), name)
} }
if m.Conf(RUNTIME, "boot.username", kit.Select(os.Getenv("USER"), os.Getenv("ctx_user"))) == "" { if m.Conf(RUNTIME, kit.Keys(BOOT, USERNAME), kit.Select(os.Getenv(USER), os.Getenv(CTX_USER))) == "" {
if user, e := user.Current(); e == nil && user.Name != "" { if user, e := user.Current(); e == nil && user.Name != "" {
m.Conf(RUNTIME, "boot.username", kit.Select(user.Name, os.Getenv("ctx_user"))) m.Conf(RUNTIME, kit.Keys(BOOT, USERNAME), kit.Select(user.Name, os.Getenv(CTX_USER)))
} }
} }
ice.Info.HostName = m.Conf(RUNTIME, "boot.hostname") ice.Info.HostName = m.Conf(RUNTIME, kit.Keys(BOOT, HOSTNAME))
ice.Info.PathName = m.Conf(RUNTIME, "boot.pathname") ice.Info.PathName = m.Conf(RUNTIME, kit.Keys(BOOT, PATHNAME))
ice.Info.UserName = m.Conf(RUNTIME, "boot.username") ice.Info.UserName = m.Conf(RUNTIME, kit.Keys(BOOT, USERNAME))
ice.Info.CtxShare = m.Conf(RUNTIME, "conf.ctx_share") ice.Info.CtxShare = m.Conf(RUNTIME, kit.Keys(CONF, CTX_SHARE))
ice.Info.CtxRiver = m.Conf(RUNTIME, "conf.ctx_river") ice.Info.CtxRiver = m.Conf(RUNTIME, kit.Keys(CONF, CTX_RIVER))
// 启动次数 // 启动次数
count := kit.Int(m.Conf(RUNTIME, "boot.count")) + 1 count := kit.Int(m.Conf(RUNTIME, kit.Keys(BOOT, kit.MDB_COUNT))) + 1
m.Conf(RUNTIME, "boot.count", count) m.Conf(RUNTIME, kit.Keys(BOOT, kit.MDB_COUNT), count)
// 节点信息 // 节点信息
m.Conf(RUNTIME, "node.time", m.Time()) m.Conf(RUNTIME, kit.Keys(NODE, kit.MDB_TIME), m.Time())
NodeInfo(m, "worker", m.Conf(RUNTIME, "boot.pathname")) NodeInfo(m, "worker", m.Conf(RUNTIME, kit.Keys(BOOT, PATHNAME)))
m.Info("runtime %v", kit.Formats(m.Confv(RUNTIME))) m.Info("runtime %v", kit.Formats(m.Confv(RUNTIME)))
n := kit.Int(kit.Select("1", m.Conf(RUNTIME, "host.GOMAXPROCS"))) n := kit.Int(kit.Select("1", m.Conf(RUNTIME, kit.Keys(HOST, "GOMAXPROCS"))))
m.Logs("host", "gomaxprocs", n) m.Logs(HOST, "GOMAXPROCS", n)
runtime.GOMAXPROCS(n) runtime.GOMAXPROCS(n)
// 版本信息 // 版本信息
kit.Fetch(kit.UnMarshal(kit.Format(ice.Info.Build)), func(key string, value interface{}) { kit.Fetch(kit.UnMarshal(kit.Format(ice.Info.Build)), func(key string, value interface{}) {
m.Conf(RUNTIME, kit.Keys("make", strings.ToLower(key)), value) m.Conf(RUNTIME, kit.Keys(MAKE, strings.ToLower(key)), value)
}) })
}}, }},
ice.CTX_EXIT: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { ice.CTX_EXIT: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {

View File

@ -37,7 +37,7 @@ func _daemon_show(m *ice.Message, cmd *exec.Cmd, out, err string) {
m.Go(func() { m.Go(func() {
h := m.Cmdx(mdb.INSERT, DAEMON, "", mdb.HASH, h := m.Cmdx(mdb.INSERT, DAEMON, "", mdb.HASH,
kit.MDB_STATUS, Status.Start, kit.SSH_PID, cmd.Process.Pid, kit.MDB_STATUS, START, kit.SSH_PID, cmd.Process.Pid,
kit.SSH_CMD, strings.Join(cmd.Args, " "), kit.SSH_CMD, strings.Join(cmd.Args, " "),
kit.SSH_DIR, cmd.Dir, kit.SSH_ENV, kit.Select("", cmd.Env), kit.SSH_DIR, cmd.Dir, kit.SSH_ENV, kit.Select("", cmd.Env),
mdb.CACHE_CLEAR_ON_EXIT, m.Option(mdb.CACHE_CLEAR_ON_EXIT), mdb.CACHE_CLEAR_ON_EXIT, m.Option(mdb.CACHE_CLEAR_ON_EXIT),
@ -46,11 +46,11 @@ func _daemon_show(m *ice.Message, cmd *exec.Cmd, out, err string) {
if e := cmd.Wait(); m.Warn(e != nil, cmd.Args, " ", e) { if e := cmd.Wait(); m.Warn(e != nil, cmd.Args, " ", e) {
m.Cmd(mdb.MODIFY, DAEMON, "", mdb.HASH, kit.MDB_HASH, h, m.Cmd(mdb.MODIFY, DAEMON, "", mdb.HASH, kit.MDB_HASH, h,
kit.MDB_STATUS, Status.Error, kit.MDB_ERROR, e) kit.MDB_STATUS, ERROR, kit.MDB_ERROR, e)
} else { } else {
m.Cost("args", cmd.Args, "code", cmd.ProcessState.ExitCode()) m.Cost("args", cmd.Args, "code", cmd.ProcessState.ExitCode())
m.Cmd(mdb.MODIFY, DAEMON, "", mdb.HASH, kit.MDB_HASH, h, m.Cmd(mdb.MODIFY, DAEMON, "", mdb.HASH, kit.MDB_HASH, h,
kit.MDB_STATUS, Status.Stop) kit.MDB_STATUS, STOP)
} }
if w, ok := m.Optionv(CMD_OUTPUT).(io.Closer); ok { if w, ok := m.Optionv(CMD_OUTPUT).(io.Closer); ok {
@ -62,12 +62,6 @@ func _daemon_show(m *ice.Message, cmd *exec.Cmd, out, err string) {
}) })
} }
var Status = struct{ Error, Start, Stop string }{
Error: "error",
Start: "start",
Stop: "stop",
}
const ( const (
DIR = "dir" DIR = "dir"
ENV = "env" ENV = "env"
@ -80,6 +74,7 @@ const (
const ( const (
RESTART = "restart" RESTART = "restart"
START = "start" START = "start"
ERROR = "error"
STOP = "stop" STOP = "stop"
) )
@ -120,7 +115,7 @@ func init() {
STOP: {Name: "stop", Help: "停止", Hand: func(m *ice.Message, arg ...string) { STOP: {Name: "stop", Help: "停止", Hand: func(m *ice.Message, arg ...string) {
m.Option(mdb.FIELDS, "time,hash,status,pid,cmd,dir,env") m.Option(mdb.FIELDS, "time,hash,status,pid,cmd,dir,env")
m.Cmd(mdb.SELECT, DAEMON, "", mdb.HASH, kit.MDB_HASH, m.Option(kit.MDB_HASH)).Table(func(index int, value map[string]string, head []string) { m.Cmd(mdb.SELECT, DAEMON, "", mdb.HASH, kit.MDB_HASH, m.Option(kit.MDB_HASH)).Table(func(index int, value map[string]string, head []string) {
m.Cmd(mdb.MODIFY, DAEMON, "", mdb.HASH, kit.MDB_HASH, m.Option(kit.MDB_HASH), kit.MDB_STATUS, Status.Stop) m.Cmd(mdb.MODIFY, DAEMON, "", mdb.HASH, kit.MDB_HASH, m.Option(kit.MDB_HASH), kit.MDB_STATUS, STOP)
m.Cmdy(SYSTEM, "kill", "-9", value[kit.SSH_PID]) m.Cmdy(SYSTEM, "kill", "-9", value[kit.SSH_PID])
}) })
}}, }},
@ -129,8 +124,8 @@ func init() {
}}, }},
mdb.PRUNES: {Name: "prunes", Help: "清理", Hand: func(m *ice.Message, arg ...string) { mdb.PRUNES: {Name: "prunes", Help: "清理", Hand: func(m *ice.Message, arg ...string) {
m.Option(mdb.FIELDS, "time,hash,status,pid,cmd,dir,env") m.Option(mdb.FIELDS, "time,hash,status,pid,cmd,dir,env")
m.Cmdy(mdb.PRUNES, DAEMON, "", mdb.HASH, kit.MDB_STATUS, Status.Error) m.Cmdy(mdb.PRUNES, DAEMON, "", mdb.HASH, kit.MDB_STATUS, ERROR)
m.Cmdy(mdb.PRUNES, DAEMON, "", mdb.HASH, kit.MDB_STATUS, Status.Stop) m.Cmdy(mdb.PRUNES, DAEMON, "", mdb.HASH, kit.MDB_STATUS, STOP)
}}, }},
}, Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { }, Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
if len(arg) == 0 { // 进程列表 if len(arg) == 0 { // 进程列表
@ -138,7 +133,7 @@ func init() {
m.Cmdy(mdb.SELECT, DAEMON, "", mdb.HASH) m.Cmdy(mdb.SELECT, DAEMON, "", mdb.HASH)
m.Table(func(index int, value map[string]string, head []string) { m.Table(func(index int, value map[string]string, head []string) {
switch value[kit.MDB_STATUS] { switch value[kit.MDB_STATUS] {
case Status.Start: case START:
m.PushButton(RESTART, STOP) m.PushButton(RESTART, STOP)
default: default:
m.PushButton(mdb.REMOVE) m.PushButton(mdb.REMOVE)

View File

@ -14,7 +14,6 @@ import (
const ( const (
DISKINFO = "diskinfo" DISKINFO = "diskinfo"
IFCONFIG = "ifconfig" IFCONFIG = "ifconfig"
HOSTNAME = "hostname"
HOSTINFO = "hostinfo" HOSTINFO = "hostinfo"
USERINFO = "userinfo" USERINFO = "userinfo"
PROCINFO = "procinfo" PROCINFO = "procinfo"
@ -41,8 +40,8 @@ func init() {
}}, }},
HOSTNAME: {Name: "hostname", Help: "主机域名", Hand: func(m *ice.Message, arg ...string) { HOSTNAME: {Name: "hostname", Help: "主机域名", Hand: func(m *ice.Message, arg ...string) {
if len(arg) > 0 { if len(arg) > 0 {
m.Conf(RUNTIME, "boot.hostname", arg[0]) m.Conf(RUNTIME, kit.Keys(NODE, kit.MDB_NAME), arg[0])
m.Conf(RUNTIME, "node.name", arg[0]) m.Conf(RUNTIME, kit.Keys(BOOT, HOSTNAME), arg[0])
ice.Info.HostName = arg[0] ice.Info.HostName = arg[0]
} }
m.Echo(ice.Info.HostName) m.Echo(ice.Info.HostName)

View File

@ -20,7 +20,7 @@ func (f *Frame) Spawn(m *ice.Message, c *ice.Context, arg ...string) ice.Server
return &Frame{} return &Frame{}
} }
func (f *Frame) Begin(m *ice.Message, arg ...string) ice.Server { func (f *Frame) Begin(m *ice.Message, arg ...string) ice.Server {
f.t = time.Tick(kit.Duration(m.Cap(ice.CTX_STREAM, ice.MOD_TICK))) f.t = time.Tick(kit.Duration(m.Conf(TIMER, kit.Keym("tick"))))
f.s = make(chan os.Signal, ice.MOD_CHAN) f.s = make(chan os.Signal, ice.MOD_CHAN)
f.e = make(chan bool, 1) f.e = make(chan bool, 1)
return f return f
@ -65,7 +65,8 @@ const GDB = "gdb"
var Index = &ice.Context{Name: GDB, Help: "事件模块", var Index = &ice.Context{Name: GDB, Help: "事件模块",
Commands: map[string]*ice.Command{ Commands: map[string]*ice.Command{
ice.CTX_INIT: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { ice.CTX_INIT: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
m.Cmd(nfs.SAVE, kit.Select(m.Conf(SIGNAL, kit.META_PATH), m.Conf(cli.RUNTIME, "conf.ctx_pid")), m.Conf(cli.RUNTIME, "host.pid")) m.Cmd(nfs.SAVE, kit.Select(m.Conf(SIGNAL, kit.META_PATH), m.Conf(cli.RUNTIME, kit.Keys(cli.CONF, cli.CTX_PID))),
m.Conf(cli.RUNTIME, kit.Keys(cli.HOST, "pid")))
m.Cmd(SIGNAL, LISTEN, SIGNAL, "3", kit.MDB_NAME, "退出", kit.SSH_CMD, "exit 0") m.Cmd(SIGNAL, LISTEN, SIGNAL, "3", kit.MDB_NAME, "退出", kit.SSH_CMD, "exit 0")
m.Cmd(SIGNAL, LISTEN, SIGNAL, "2", kit.MDB_NAME, "重启", kit.SSH_CMD, "exit 1") m.Cmd(SIGNAL, LISTEN, SIGNAL, "2", kit.MDB_NAME, "重启", kit.SSH_CMD, "exit 1")

View File

@ -1,7 +1,9 @@
package gdb package gdb
import ( import (
"os"
"os/signal" "os/signal"
"path"
"syscall" "syscall"
ice "github.com/shylinux/icebergs" ice "github.com/shylinux/icebergs"
@ -23,6 +25,18 @@ func _signal_action(m *ice.Message, s int) {
}) })
} }
func SignalNotify(m *ice.Message, sig int, cb func()) {
ch := make(chan os.Signal)
signal.Notify(ch, syscall.Signal(sig))
m.Go(func() {
for {
if _, ok := <-ch; ok {
cb()
}
}
})
}
const ( const (
LISTEN = "listen" LISTEN = "listen"
ACTION = "action" ACTION = "action"
@ -33,7 +47,7 @@ func init() {
Index.Merge(&ice.Context{ Index.Merge(&ice.Context{
Configs: map[string]*ice.Config{ Configs: map[string]*ice.Config{
SIGNAL: {Name: SIGNAL, Help: "信号器", Value: kit.Data( SIGNAL: {Name: SIGNAL, Help: "信号器", Value: kit.Data(
kit.MDB_PATH, "var/run/ice.pid", kit.MDB_SHORT, SIGNAL, kit.MDB_PATH, path.Join(ice.VAR_RUN, "ice.pid"), kit.MDB_SHORT, SIGNAL,
)}, )},
}, },
Commands: map[string]*ice.Command{ Commands: map[string]*ice.Command{

View File

@ -9,7 +9,7 @@ import (
) )
func _timer_create(m *ice.Message, arg ...string) { func _timer_create(m *ice.Message, arg ...string) {
m.Cmdy(mdb.INSERT, TIMER, "", mdb.HASH, "delay", "10ms", "interval", "10m", "order", 1, "next", m.Time(m.Option("delay")), arg) m.Cmdy(mdb.INSERT, TIMER, "", mdb.HASH, DELAY, "10ms", INTERVAL, "10m", ORDER, 1, NEXT, m.Time(m.Option(DELAY)), arg)
} }
func _timer_action(m *ice.Message, arg ...string) { func _timer_action(m *ice.Message, arg ...string) {
now := time.Now().UnixNano() now := time.Now().UnixNano()
@ -20,19 +20,25 @@ func _timer_action(m *ice.Message, arg ...string) {
return return
} }
order := kit.Int(value["order"]) order := kit.Int(value[ORDER])
if n := kit.Time(kit.Format(value["next"])); now > n && order > 0 { if n := kit.Time(kit.Format(value[NEXT])); now > n && order > 0 {
m.Logs(TIMER, "key", key, "order", order) m.Logs(TIMER, kit.MDB_KEY, key, ORDER, order)
msg := m.Cmd(value[kit.SSH_CMD]) msg := m.Cmd(value[kit.SSH_CMD])
m.Grow(TIMER, kit.Keys(kit.MDB_HASH, key), kit.Dict("res", msg.Result())) m.Grow(TIMER, kit.Keys(kit.MDB_HASH, key), kit.Dict("res", msg.Result()))
if value["order"] = kit.Format(order - 1); order > 1 { if value[ORDER] = kit.Format(order - 1); order > 1 {
value["next"] = msg.Time(value["interval"]) value[NEXT] = msg.Time(value[INTERVAL])
} }
} }
}) })
} }
const (
DELAY = "delay"
INTERVAL = "interval"
ORDER = "order"
NEXT = "next"
)
const TIMER = "timer" const TIMER = "timer"
func init() { func init() {
@ -53,7 +59,7 @@ func init() {
}}, }},
mdb.PRUNES: {Name: "prunes", Help: "清理", Hand: func(m *ice.Message, arg ...string) { mdb.PRUNES: {Name: "prunes", Help: "清理", Hand: func(m *ice.Message, arg ...string) {
m.Option(mdb.FIELDS, "time,hash,delay,interval,order,next,cmd") m.Option(mdb.FIELDS, "time,hash,delay,interval,order,next,cmd")
m.Cmdy(mdb.PRUNES, TIMER, "", mdb.HASH, "order", 0) m.Cmdy(mdb.PRUNES, TIMER, "", mdb.HASH, ORDER, 0)
}}, }},
ACTION: {Name: "action", Help: "执行", Hand: func(m *ice.Message, arg ...string) { ACTION: {Name: "action", Help: "执行", Hand: func(m *ice.Message, arg ...string) {

View File

@ -13,7 +13,7 @@ import (
) )
func _file_name(m *ice.Message, arg ...string) string { func _file_name(m *ice.Message, arg ...string) string {
return kit.Select(path.Join(m.Option(ice.MSG_LOCAL), "usr/local/export", path.Join(arg[:2]...), arg[2]), arg, 3) return kit.Select(path.Join(m.Option(ice.MSG_LOCAL), ice.USR_LOCAL, EXPORT, path.Join(arg[:2]...), arg[2]), arg, 3)
} }
func _domain_chain(m *ice.Message, chain string) string { func _domain_chain(m *ice.Message, chain string) string {
return kit.Keys(m.Option(ice.MSG_DOMAIN), chain) return kit.Keys(m.Option(ice.MSG_DOMAIN), chain)
@ -157,7 +157,7 @@ func _list_select(m *ice.Message, prefix, chain, field, value string) {
} }
fields := _list_fields(m) fields := _list_fields(m)
cb := m.Optionv(kit.Keycb(SELECT)) cb := m.Optionv(kit.Keycb(SELECT))
m.Grows(prefix, chain, kit.Select(m.Option("cache.field"), field), kit.Select(m.Option(CACHE_VALUE), value), func(index int, val map[string]interface{}) { m.Grows(prefix, chain, kit.Select(m.Option(CACHE_FIELD), field), kit.Select(m.Option(CACHE_VALUE), value), func(index int, val map[string]interface{}) {
val = kit.GetMeta(val) val = kit.GetMeta(val)
switch cb := cb.(type) { switch cb := cb.(type) {
case func(fields []string, value map[string]interface{}): case func(fields []string, value map[string]interface{}):
@ -263,7 +263,7 @@ func _list_inputs(m *ice.Message, prefix, chain string, field, value string) {
m.Push(field, k) m.Push(field, k)
m.Push(kit.MDB_COUNT, i) m.Push(kit.MDB_COUNT, i)
} }
m.Sort(kit.MDB_COUNT, "int_r") m.SortIntR(kit.MDB_COUNT)
} }
func _zone_fields(m *ice.Message) []string { func _zone_fields(m *ice.Message) []string {
@ -404,6 +404,7 @@ const (
SELECT = "select" SELECT = "select"
DELETE = "delete" DELETE = "delete"
REMOVE = "remove" REMOVE = "remove"
REVERT = "revert"
EXPORT = "export" EXPORT = "export"
IMPORT = "import" IMPORT = "import"
@ -412,14 +413,9 @@ const (
) )
const ( const (
CACHE_LIMIT = "cache.limit" CACHE_LIMIT = "cache.limit"
CACHE_FILED = "cache.field" CACHE_FIELD = "cache.field"
CACHE_VALUE = "cache.value" CACHE_VALUE = "cache.value"
CACHE_STATUS = "cache.status"
CACHE_ACTION = "cache.action"
CACHE_BEGIN = "cache.begin"
CACHE_HASH = "cache.hash"
CACHE_CLEAR_ON_EXIT = "cache.clear.on.exit" CACHE_CLEAR_ON_EXIT = "cache.clear.on.exit"
) )

View File

@ -178,7 +178,7 @@ func init() {
_dir_search(m, arg[0], arg[1]) _dir_search(m, arg[0], arg[1])
}}, }},
mdb.RENDER: {Name: "render type name text", Help: "渲染", Hand: func(m *ice.Message, arg ...string) { mdb.RENDER: {Name: "render type name text", Help: "渲染", Hand: func(m *ice.Message, arg ...string) {
_dir_show(m, arg[2], arg[1], 0, m.Option(DIR_DEEP) == "true", kit.Select(TYPE_BOTH, m.Option(DIR_TYPE)), _dir_show(m, arg[2], arg[1], 0, m.Option(DIR_DEEP) == ice.TRUE, kit.Select(TYPE_BOTH, m.Option(DIR_TYPE)),
nil, kit.Split("time,size,type,path")) nil, kit.Split("time,size,type,path"))
}}, }},

View File

@ -28,7 +28,7 @@ func _tail_create(m *ice.Message, arg ...string) {
m.Option(cli.CMD_OUTPUT, w) m.Option(cli.CMD_OUTPUT, w)
m.Option(cli.CMD_ERRPUT, w) m.Option(cli.CMD_ERRPUT, w)
m.Option(mdb.CACHE_CLEAR_ON_EXIT, "true") m.Option(mdb.CACHE_CLEAR_ON_EXIT, ice.TRUE)
m.Cmd(cli.DAEMON, TAIL, "-n", "0", "-f", file) m.Cmd(cli.DAEMON, TAIL, "-n", "0", "-f", file)
}) })
} }
@ -55,7 +55,6 @@ func init() {
offend = total - kit.Int(kit.Select("10", arg, 2)) offend = total - kit.Int(kit.Select("10", arg, 2))
m.Toast("已经是最后一页啦!") m.Toast("已经是最后一页啦!")
} }
m.ProcessRewrite("offend", offend) m.ProcessRewrite("offend", offend)
}}, }},
"next": {Name: "next", Help: "下一页", Hand: func(m *ice.Message, arg ...string) { "next": {Name: "next", Help: "下一页", Hand: func(m *ice.Message, arg ...string) {
@ -68,7 +67,7 @@ func init() {
}}, }},
}, Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { }, Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
m.Option(mdb.FIELDS, kit.Select("time,hash,count,name,file", kit.Select("time,id,file,text", mdb.DETAIL, len(arg) > 1 && arg[1] != ""), len(arg) > 0)) m.Option(mdb.FIELDS, kit.Select("time,hash,count,name,file", kit.Select("time,id,file,text", mdb.DETAIL, len(arg) > 1 && arg[1] != ""), len(arg) > 0))
m.Option("cache.limit", kit.Select("10", arg, 2)) m.Option(mdb.CACHE_LIMIT, kit.Select("10", arg, 2))
m.Option("cache.offend", kit.Select("0", arg, 3)) m.Option("cache.offend", kit.Select("0", arg, 3))
if m.Cmdy(mdb.SELECT, TAIL, "", mdb.ZONE, arg); len(arg) == 0 { if m.Cmdy(mdb.SELECT, TAIL, "", mdb.ZONE, arg); len(arg) == 0 {

View File

@ -44,7 +44,7 @@ func init() {
}, },
Commands: map[string]*ice.Command{ Commands: map[string]*ice.Command{
TRASH: {Name: "trash file auto prunes", Help: "回收站", Action: map[string]*ice.Action{ TRASH: {Name: "trash file auto prunes", Help: "回收站", Action: map[string]*ice.Action{
"recover": {Name: "recover", Help: "恢复", Hand: func(m *ice.Message, arg ...string) { mdb.REVERT: {Name: "revert", Help: "恢复", Hand: func(m *ice.Message, arg ...string) {
os.Rename(m.Option(kit.MDB_FILE), m.Option(kit.MDB_FROM)) os.Rename(m.Option(kit.MDB_FILE), m.Option(kit.MDB_FROM))
m.Cmd(mdb.DELETE, TRASH, "", mdb.HASH, kit.MDB_HASH, m.Option(kit.MDB_HASH)) m.Cmd(mdb.DELETE, TRASH, "", mdb.HASH, kit.MDB_HASH, m.Option(kit.MDB_HASH))
}}, }},
@ -59,7 +59,7 @@ func init() {
if len(arg) == 0 { if len(arg) == 0 {
m.Option(mdb.FIELDS, "time,hash,file,from") m.Option(mdb.FIELDS, "time,hash,file,from")
m.Cmdy(mdb.SELECT, TRASH, "", mdb.HASH) m.Cmdy(mdb.SELECT, TRASH, "", mdb.HASH)
m.PushAction("recover", mdb.REMOVE) m.PushAction(mdb.REVERT, mdb.REMOVE)
return return
} }
_trash_create(m, arg[0]) _trash_create(m, arg[0])

View File

@ -8,11 +8,11 @@ import (
"os" "os"
"path" "path"
"strings" "strings"
"time"
ice "github.com/shylinux/icebergs" ice "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/cli"
"github.com/shylinux/icebergs/base/gdb"
"github.com/shylinux/icebergs/base/mdb" "github.com/shylinux/icebergs/base/mdb"
"github.com/shylinux/icebergs/base/nfs" "github.com/shylinux/icebergs/base/nfs"
"github.com/shylinux/icebergs/base/tcp" "github.com/shylinux/icebergs/base/tcp"
@ -21,72 +21,103 @@ import (
"golang.org/x/crypto/ssh/terminal" "golang.org/x/crypto/ssh/terminal"
) )
func _ssh_tick(m *ice.Message, pw io.Writer) { func _ssh_open(m *ice.Message, arg ...string) {
if m.Option("tick") == "" { // 加载配置
return if f, e := os.Open(m.Option("authfile")); e == nil {
}
m.Go(func() {
for {
m.Sleep(m.Option("tick"))
pw.Write([]byte("# " + time.Now().Format(ice.MOD_TIME) + "\n"))
}
})
}
func _ssh_password(m *ice.Message, file string) {
if f, e := os.Open(file); e == nil {
defer f.Close() defer f.Close()
var data interface{} var data interface{}
json.NewDecoder(f).Decode(&data) json.NewDecoder(f).Decode(&data)
kit.Fetch(data, func(key string, value string) { m.Option(key, value) }) kit.Fetch(data, func(key string, value interface{}) { m.Option(key, kit.Simple(value)) })
}
}
func _ssh_stream(m *ice.Message, stdin *os.File) (io.Reader, io.Writer) {
pr, pw := io.Pipe()
m.Go(func() {
buf := make([]byte, 1024)
for {
if n, e := stdin.Read(buf); m.Assert(e) {
pw.Write(buf[:n])
}
}
})
return pr, pw
}
func _ssh_store(stdio *os.File) func() {
fd := int(stdio.Fd())
oldState, err := terminal.MakeRaw(fd)
if err != nil {
panic(err)
}
return func() { terminal.Restore(fd, oldState) }
} }
func _ssh_session(m *ice.Message, client *ssh.Client, w, h int, stdin io.Reader, stdout, stderr io.Writer) *ssh.Session { _ssh_dial(m, func(c net.Conn) {
// 保存界面
fd := int(os.Stdin.Fd())
if oldState, err := terminal.MakeRaw(fd); err == nil {
defer terminal.Restore(fd, oldState)
}
// 设置宽高
w, h, _ := terminal.GetSize(fd)
c.Write([]byte(fmt.Sprintf("height:%d,width:%d\n", h, w)))
// 初始命令
for _, item := range kit.Simple(m.Optionv("list")) {
m.Sleep("10ms")
c.Write([]byte(item + "\n"))
}
m.Go(func() { io.Copy(os.Stdout, c) })
io.Copy(c, os.Stdin)
}, arg...)
}
func _ssh_dial(m *ice.Message, cb func(net.Conn), arg ...string) {
p := path.Join(os.Getenv(cli.HOME), ".ssh/", fmt.Sprintf("%s@%s:%s", m.Option(aaa.USERNAME), m.Option(tcp.HOST), m.Option(tcp.PORT)))
if _, e := os.Stat(p); e == nil {
if c, e := net.Dial("unix", p); e == nil {
cb(c) // 会话连接
return
}
os.Remove(p)
}
var client *ssh.Client
if l, e := net.Listen("unix", p); m.Assert(e) {
defer func() { os.Remove(p) }()
defer l.Close()
m.Go(func() {
for {
c, e := l.Accept()
m.Assert(e)
func(c net.Conn) {
w, h, _ := terminal.GetSize(int(os.Stdin.Fd()))
buf := make([]byte, ice.MOD_BUFS)
if n, e := c.Read(buf); m.Assert(e) {
fmt.Sscanf(string(buf[:n]), "height:%d,width:%d", &h, &w)
}
m.Go(func() {
defer c.Close()
session, e := client.NewSession() session, e := client.NewSession()
m.Assert(e) m.Assert(e)
session.Stdin = stdin session.Stdin = c
session.Stdout = stdout session.Stdout = c
session.Stderr = stderr session.Stderr = c
modes := ssh.TerminalModes{ session.RequestPty(os.Getenv("TERM"), h, w, ssh.TerminalModes{
ssh.ECHO: 1, ssh.ECHO: 1,
ssh.TTY_OP_ISPEED: 14400, ssh.TTY_OP_ISPEED: 14400,
ssh.TTY_OP_OSPEED: 14400, ssh.TTY_OP_OSPEED: 14400,
})
gdb.SignalNotify(m, 28, func() {
w, h, _ := terminal.GetSize(int(os.Stdin.Fd()))
session.WindowChange(h, w)
})
session.Shell()
session.Wait()
})
}(c)
}
})
} }
session.RequestPty(os.Getenv("TERM"), h, w, modes) m.Option(kit.Keycb(tcp.DIAL), func(c net.Conn) {
session.Shell() client = _ssh_conn(m, c, m.Option(aaa.USERNAME), m.Option(tcp.HOST)+":"+m.Option(tcp.PORT))
return session
} if c, e := net.Dial("unix", p); e == nil {
func _ssh_init(m *ice.Message, pw io.Writer) { cb(c) // 会话连接
for _, k := range []string{"one", "two"} {
if m.Sleep("100ms"); m.Option(k) != "" {
pw.Write([]byte(m.Option(k) + "\n"))
}
} }
})
m.Cmdy(tcp.CLIENT, tcp.DIAL, kit.MDB_TYPE, SSH, kit.MDB_NAME, m.Option(tcp.HOST),
tcp.PORT, m.Option(tcp.PORT), tcp.HOST, m.Option(tcp.HOST), arg)
} }
func _ssh_conn(m *ice.Message, conn net.Conn, username, hostport string) *ssh.Client { func _ssh_conn(m *ice.Message, conn net.Conn, username, hostport string) *ssh.Client {
methods := []ssh.AuthMethod{} methods := []ssh.AuthMethod{}
@ -128,76 +159,6 @@ func _ssh_conn(m *ice.Message, conn net.Conn, username, hostport string) *ssh.Cl
return ssh.NewClient(c, chans, reqs) return ssh.NewClient(c, chans, reqs)
} }
func _ssh_open(m *ice.Message, arg ...string) {
var client *ssh.Client
w, h, _ := terminal.GetSize(int(os.Stdin.Fd()))
_ssh_password(m, m.Option("authfile"))
p := path.Join(os.Getenv("HOME"), ".ssh/", fmt.Sprintf("%s@%s", m.Option("username"), m.Option("host")))
if _, e := os.Stat(p); e == nil {
if c, e := net.Dial("unix", p); e == nil {
pr, pw := _ssh_stream(m, os.Stdin)
defer _ssh_store(os.Stdout)()
defer _ssh_store(os.Stdin)()
c.Write([]byte(fmt.Sprintf("height:%d,width:%d\n", h, w)))
m.Go(func() { io.Copy(c, pr) })
_ssh_init(m, pw)
m.Echo("logout\n")
io.Copy(os.Stdout, c)
return
} else {
os.Remove(p)
}
}
if l, e := net.Listen("unix", p); m.Assert(e) {
defer func() { os.Remove(p) }()
defer l.Close()
m.Go(func() {
for {
if c, e := l.Accept(); e == nil {
buf := make([]byte, 1024)
if n, e := c.Read(buf); m.Assert(e) {
fmt.Sscanf(string(buf[:n]), "height:%d,width:%d", &h, &w)
}
session := _ssh_session(m, client, w, h, c, c, c)
func(session *ssh.Session) {
m.Go(func() {
defer c.Close()
session.Wait()
})
}(session)
} else {
break
}
}
})
}
m.Option(kit.Keycb(tcp.DIAL), func(c net.Conn) {
client = _ssh_conn(m, c, m.Option(aaa.USERNAME), m.Option(tcp.HOST)+":"+m.Option(tcp.PORT))
pr, pw := _ssh_stream(m, os.Stdin)
defer _ssh_store(os.Stdout)()
defer _ssh_store(os.Stdin)()
session := _ssh_session(m, client, w, h, pr, os.Stdout, os.Stderr)
_ssh_init(m, pw)
_ssh_tick(m, pw)
session.Wait()
})
m.Cmdy(tcp.CLIENT, tcp.DIAL, kit.MDB_TYPE, "ssh", kit.MDB_NAME, m.Option(tcp.HOST),
tcp.PORT, m.Option(tcp.PORT), tcp.HOST, m.Option(tcp.HOST), arg)
m.Echo("exit %s\n", m.Option(tcp.HOST))
}
const CONNECT = "connect" const CONNECT = "connect"
func init() { func init() {
@ -207,6 +168,9 @@ func init() {
}, },
Commands: map[string]*ice.Command{ Commands: map[string]*ice.Command{
CONNECT: {Name: "connect hash auto dial prunes", Help: "连接", Action: map[string]*ice.Action{ CONNECT: {Name: "connect hash auto dial prunes", Help: "连接", Action: map[string]*ice.Action{
tcp.OPEN: {Name: "open authfile= username=shy password= verfiy= host=shylinux.com port=22 private=.ssh/id_rsa", Help: "终端", Hand: func(m *ice.Message, arg ...string) {
_ssh_open(m, arg...)
}},
tcp.DIAL: {Name: "dial username=shy host=shylinux.com port=22 private=.ssh/id_rsa", Help: "添加", Hand: func(m *ice.Message, arg ...string) { 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(kit.Keycb(tcp.DIAL), func(c net.Conn) { m.Option(kit.Keycb(tcp.DIAL), func(c net.Conn) {
client := _ssh_conn(m, c, kit.Select("shy", m.Option(aaa.USERNAME)), client := _ssh_conn(m, c, kit.Select("shy", m.Option(aaa.USERNAME)),
@ -225,9 +189,6 @@ func init() {
m.Cmds(tcp.CLIENT, tcp.DIAL, kit.MDB_TYPE, SSH, kit.MDB_NAME, m.Option(aaa.USERNAME), m.Cmds(tcp.CLIENT, tcp.DIAL, kit.MDB_TYPE, SSH, kit.MDB_NAME, m.Option(aaa.USERNAME),
tcp.PORT, m.Option(tcp.PORT), tcp.HOST, m.Option(tcp.HOST)) tcp.PORT, m.Option(tcp.PORT), tcp.HOST, m.Option(tcp.HOST))
}}, }},
tcp.OPEN: {Name: "open authfile= username=shy password= verfiy= host=shylinux.com port=22 private=.ssh/id_rsa tick=", Help: "终端", Hand: func(m *ice.Message, arg ...string) {
_ssh_open(m, arg...)
}},
mdb.REMOVE: {Name: "remove", Help: "删除", Hand: func(m *ice.Message, arg ...string) { mdb.REMOVE: {Name: "remove", Help: "删除", Hand: func(m *ice.Message, arg ...string) {
m.Cmdy(mdb.DELETE, CONNECT, "", mdb.HASH, kit.MDB_HASH, m.Option(kit.MDB_HASH)) m.Cmdy(mdb.DELETE, CONNECT, "", mdb.HASH, kit.MDB_HASH, m.Option(kit.MDB_HASH))
}}, }},
@ -243,7 +204,7 @@ func init() {
h := m.Rich(SESSION, "", kit.Data(kit.MDB_STATUS, tcp.OPEN, CONNECT, key)) h := m.Rich(SESSION, "", kit.Data(kit.MDB_STATUS, tcp.OPEN, CONNECT, key))
if session, e := _ssh_sess(m, h, client); m.Assert(e) { if session, e := _ssh_session(m, h, client); m.Assert(e) {
session.Shell() session.Shell()
session.Wait() session.Wait()
} }

View File

@ -3,7 +3,6 @@ package ssh
import ( import (
"golang.org/x/crypto/ssh" "golang.org/x/crypto/ssh"
"io" "io"
"os"
ice "github.com/shylinux/icebergs" ice "github.com/shylinux/icebergs"
"github.com/shylinux/icebergs/base/ctx" "github.com/shylinux/icebergs/base/ctx"
@ -12,7 +11,7 @@ import (
kit "github.com/shylinux/toolkits" kit "github.com/shylinux/toolkits"
) )
func _ssh_sess(m *ice.Message, h string, client *ssh.Client) (*ssh.Session, error) { func _ssh_session(m *ice.Message, h string, client *ssh.Client) (*ssh.Session, error) {
session, e := client.NewSession() session, e := client.NewSession()
m.Assert(e) m.Assert(e)
@ -23,14 +22,13 @@ func _ssh_sess(m *ice.Message, h string, client *ssh.Client) (*ssh.Session, erro
m.Assert(e) m.Assert(e)
m.Go(func() { m.Go(func() {
for {
buf := make([]byte, 4096) buf := make([]byte, 4096)
for {
n, e := out.Read(buf) n, e := out.Read(buf)
if e != nil { if e != nil {
break break
} }
m.Debug(string(buf[:n]))
m.Grow(SESSION, kit.Keys(kit.MDB_HASH, h), kit.Dict( m.Grow(SESSION, kit.Keys(kit.MDB_HASH, h), kit.Dict(
kit.MDB_TYPE, RES, kit.MDB_TEXT, string(buf[:n]), kit.MDB_TYPE, RES, kit.MDB_TEXT, string(buf[:n]),
)) ))
@ -38,35 +36,24 @@ func _ssh_sess(m *ice.Message, h string, client *ssh.Client) (*ssh.Session, erro
}) })
m.Richs(SESSION, "", h, func(key string, value map[string]interface{}) { m.Richs(SESSION, "", h, func(key string, value map[string]interface{}) {
kit.Value(value, "meta.output", out) kit.Value(value, kit.Keym(OUTPUT), out)
kit.Value(value, "meta.input", in) kit.Value(value, kit.Keym(INPUT), in)
}) })
return session, nil return session, nil
} }
func _watch(m *ice.Message, from io.Reader, to io.Writer, cb func([]byte)) {
m.Go(func() {
buf := make([]byte, 1024)
for {
n, e := from.Read(buf)
if e != nil {
cb(nil)
break
}
cb(buf[:n])
to.Write(buf[:n])
}
})
}
const ( const (
TTY = "tty" TTY = "tty"
ENV = "env" ENV = "env"
ARG = "arg"
CMD = "cmd" CMD = "cmd"
ARG = "arg"
RES = "res" RES = "res"
) )
const (
INPUT = "input"
OUTPUT = "output"
)
const SESSION = "session" const SESSION = "session"
@ -77,9 +64,16 @@ func init() {
}, },
Commands: map[string]*ice.Command{ Commands: map[string]*ice.Command{
SESSION: {Name: "session hash id auto command prunes", Help: "会话", Action: map[string]*ice.Action{ SESSION: {Name: "session hash id auto command prunes", Help: "会话", Action: map[string]*ice.Action{
mdb.REMOVE: {Name: "remove", Help: "删除", Hand: func(m *ice.Message, arg ...string) {
m.Cmdy(mdb.DELETE, SESSION, "", mdb.HASH, kit.MDB_HASH, m.Option(kit.MDB_HASH))
}},
mdb.PRUNES: {Name: "prunes", Help: "清理", Hand: func(m *ice.Message, arg ...string) {
m.Cmdy(mdb.PRUNES, SESSION, "", mdb.HASH, kit.MDB_STATUS, tcp.ERROR)
m.Cmdy(mdb.PRUNES, SESSION, "", mdb.HASH, kit.MDB_STATUS, tcp.CLOSE)
}},
ctx.COMMAND: {Name: "command cmd=pwd", Help: "命令", Hand: func(m *ice.Message, arg ...string) { ctx.COMMAND: {Name: "command cmd=pwd", Help: "命令", Hand: func(m *ice.Message, arg ...string) {
m.Richs(SESSION, "", m.Option(kit.MDB_HASH), func(key string, value map[string]interface{}) { m.Richs(SESSION, "", m.Option(kit.MDB_HASH), func(key string, value map[string]interface{}) {
if w, ok := kit.Value(value, "meta.input").(io.Writer); ok { if w, ok := kit.Value(value, kit.Keym(INPUT)).(io.Writer); ok {
m.Grow(SESSION, kit.Keys(kit.MDB_HASH, key), kit.Dict(kit.MDB_TYPE, CMD, kit.MDB_TEXT, m.Option(CMD))) m.Grow(SESSION, kit.Keys(kit.MDB_HASH, key), kit.Dict(kit.MDB_TYPE, CMD, kit.MDB_TEXT, m.Option(CMD)))
n, e := w.Write([]byte(m.Option(CMD) + "\n")) n, e := w.Write([]byte(m.Option(CMD) + "\n"))
m.Debug("%v %v", n, e) m.Debug("%v %v", n, e)
@ -87,42 +81,19 @@ func init() {
}) })
m.ProcessRefresh("300ms") m.ProcessRefresh("300ms")
}}, }},
"bind": {Name: "bind", Help: "绑定", Hand: func(m *ice.Message, arg ...string) {
m.Richs(SESSION, "", m.Option(kit.MDB_HASH), func(key string, value map[string]interface{}) {
value = kit.GetMeta(value)
input := value["input"].(io.Writer)
_watch(m, os.Stdin, input, func(buf []byte) {
m.Debug("input %v", string(buf))
})
output := value["output"].(io.Reader)
_watch(m, output, os.Stdout, func(buf []byte) {
m.Debug("output %v", string(buf))
})
})
}},
mdb.REMOVE: {Name: "remove", Help: "删除", Hand: func(m *ice.Message, arg ...string) {
m.Cmdy(mdb.DELETE, SESSION, "", mdb.HASH, kit.MDB_HASH, m.Option(kit.MDB_HASH))
}},
mdb.PRUNES: {Name: "prunes", Help: "清理", Hand: func(m *ice.Message, arg ...string) {
m.Cmdy(mdb.PRUNES, SESSION, "", mdb.HASH, kit.MDB_STATUS, tcp.CLOSE)
}},
}, Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { }, Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
if len(arg) == 0 { if len(arg) == 0 {
m.Option(mdb.FIELDS, "time,hash,status,count,connect") m.Option(mdb.FIELDS, "time,hash,status,count,connect")
if m.Cmdy(mdb.SELECT, SESSION, "", mdb.HASH, kit.MDB_HASH, arg); len(arg) == 0 { if m.Cmdy(mdb.SELECT, SESSION, "", mdb.HASH, kit.MDB_HASH, arg); len(arg) == 0 {
m.Table(func(index int, value map[string]string, head []string) { m.Table(func(index int, value map[string]string, head []string) {
m.PushButton(kit.Select("bind", mdb.REMOVE, value[kit.MDB_STATUS] == tcp.CLOSE)) m.PushButton(kit.Select("", mdb.REMOVE, value[kit.MDB_STATUS] == tcp.CLOSE))
}) })
} }
return return
} }
m.Option(mdb.FIELDS, kit.Select("time,id,type,text", mdb.DETAIL, len(arg) > 1)) m.Fields(len(arg) == 1, "time,id,type,text")
m.Cmdy(mdb.SELECT, SESSION, kit.Keys(kit.MDB_HASH, arg[0]), mdb.LIST, kit.MDB_ID, arg[1:]) m.Cmdy(mdb.SELECT, SESSION, kit.Keys(kit.MDB_HASH, arg[0]), mdb.LIST, kit.MDB_ID, arg[1:])
m.Sort(kit.MDB_ID)
}}, }},
}, },
}) })

View File

@ -40,6 +40,7 @@ const ( // DIR
INDEX_SH = "index.sh" INDEX_SH = "index.sh"
VAR_TMP = "var/tmp" VAR_TMP = "var/tmp"
VAR_RUN = "var/run"
VAR_LOG = "var/log" VAR_LOG = "var/log"
VAR_CONF = "var/conf" VAR_CONF = "var/conf"
VAR_DATA = "var/data" VAR_DATA = "var/data"

View File

@ -1,13 +1,13 @@
package ice package ice
import ( import (
kit "github.com/shylinux/toolkits"
"github.com/shylinux/toolkits/task"
"errors" "errors"
"fmt" "fmt"
"io" "io"
"time" "time"
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 {