1
0
forked from x/icebergs
This commit is contained in:
shaoying 2020-10-03 10:12:42 +08:00
parent b5d5de5f3a
commit a3da6968ca
21 changed files with 396 additions and 273 deletions

View File

@ -3,13 +3,16 @@ package aaa
import (
ice "github.com/shylinux/icebergs"
"github.com/shylinux/icebergs/base/cli"
"github.com/shylinux/icebergs/base/gdb"
"github.com/shylinux/icebergs/base/mdb"
kit "github.com/shylinux/toolkits"
"strings"
)
const (
USER_CREATE = "user.create"
)
func _user_list(m *ice.Message) {
m.Richs(USER, nil, kit.MDB_FOREACH, func(key string, value map[string]interface{}) {
m.Push(key, value, []string{kit.MDB_TIME, USERZONE, USERNICK, USERNAME})
@ -50,7 +53,7 @@ func _user_create(m *ice.Message, name, word string) {
USERNODE, cli.NodeName,
))
m.Log_CREATE(USERNAME, name, "hash", h)
m.Event(gdb.USER_CREATE, name)
m.Event(USER_CREATE, name)
}
func _user_search(m *ice.Message, kind, name, text string, arg ...string) {
m.Richs(USER, nil, kit.MDB_FOREACH, func(key string, val map[string]interface{}) {

View File

@ -60,7 +60,7 @@ func _config_load(m *ice.Message, name string, arg ...string) {
for k, v := range data {
msg.Search(k, func(p *ice.Context, s *ice.Context, key string) {
m.Log_IMPORT(CONFIG, kit.Keys(s.Name, key), kit.MDB_FILE, name)
// m.Log_IMPORT(CONFIG, kit.Keys(s.Name, key), kit.MDB_FILE, name)
s.Configs[key].Value = v
})
}

56
base/gdb/event.go Normal file
View File

@ -0,0 +1,56 @@
package gdb
import (
ice "github.com/shylinux/icebergs"
"github.com/shylinux/icebergs/base/mdb"
kit "github.com/shylinux/toolkits"
)
func _event_listen(m *ice.Message, event string, cmd string) {
h := m.Cmdx(mdb.INSERT, EVENT, "", mdb.HASH, EVENT, event)
m.Cmdy(mdb.INSERT, EVENT, kit.Keys(kit.MDB_HASH, h), mdb.LIST, kit.SSH_CMD, cmd)
}
func _event_action(m *ice.Message, event string, arg ...string) {
m.Option(mdb.FIELDS, "time,id,cmd")
m.Cmd(mdb.SELECT, EVENT, kit.Keys(kit.MDB_HASH, kit.Hashs(event)), mdb.LIST).Table(func(index int, value map[string]string, head []string) {
m.Cmd(kit.Split(value[kit.SSH_CMD]), event, arg).Cost("event %v %v", event, arg)
})
}
const EVENT = "event"
func init() {
Index.Merge(&ice.Context{
Configs: map[string]*ice.Config{
EVENT: {Name: EVENT, Help: "事件流", Value: kit.Data(
kit.MDB_SHORT, EVENT,
)},
},
Commands: map[string]*ice.Command{
EVENT: {Name: "event event id auto 监听", Help: "事件流", Action: map[string]*ice.Action{
LISTEN: {Name: "listen event cmd", Help: "监听", Hand: func(m *ice.Message, arg ...string) {
_event_listen(m, m.Option(EVENT), m.Option(kit.SSH_CMD))
}},
ACTION: {Name: "action event arg", Help: "触发", Hand: func(m *ice.Message, arg ...string) {
_event_action(m, m.Option(EVENT), arg[2:]...)
}},
mdb.REMOVE: {Name: "remove", Help: "删除", Hand: func(m *ice.Message, arg ...string) {
m.Cmdy(mdb.DELETE, EVENT, "", mdb.HASH, EVENT, m.Option(EVENT))
}},
}, Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
if len(arg) == 0 {
m.Option(mdb.FIELDS, "time,event,count")
m.Cmdy(mdb.SELECT, EVENT, "", mdb.HASH)
m.PushAction(ACTION, mdb.REMOVE)
return
}
m.Option(mdb.FIELDS, kit.Select("time,id,cmd", mdb.DETAIL, len(arg) > 1))
m.Cmdy(mdb.SELECT, EVENT, kit.Keys(kit.MDB_HASH, kit.Hashs(arg[0])), mdb.LIST, kit.MDB_ID, arg[1:])
if len(arg) == 1 {
m.Sort(kit.MDB_ID)
}
}},
},
}, nil)
}

View File

@ -3,67 +3,39 @@ package gdb
import (
ice "github.com/shylinux/icebergs"
"github.com/shylinux/icebergs/base/cli"
"github.com/shylinux/icebergs/base/mdb"
"github.com/shylinux/icebergs/base/nfs"
kit "github.com/shylinux/toolkits"
"os"
"os/signal"
"syscall"
"time"
)
type Frame struct {
s chan os.Signal
t <-chan time.Time
d chan []string
s chan os.Signal
e chan bool
}
func (f *Frame) Spawn(m *ice.Message, c *ice.Context, arg ...string) ice.Server {
return &Frame{}
}
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.s = make(chan os.Signal, ice.MOD_CHAN)
f.e = make(chan bool, 1)
return f
}
func (f *Frame) Start(m *ice.Message, arg ...string) bool {
for {
select {
case s, ok := <-f.s:
if !ok {
return true
}
// 信号事件
m.Logs(EVENT, SIGNAL, s)
m.Cmd(m.Confv(SIGNAL, kit.Keys(kit.MDB_HASH, s)), kit.Keys(s))
case <-f.e:
return true
case t, ok := <-f.t:
if !ok {
return true
}
case s := <-f.s:
m.Cmd(SIGNAL, ACTION, SIGNAL, s)
// 定时事件
stamp := int(t.Unix())
m.Confm(TIMER, kit.MDB_HASH, func(key string, value map[string]interface{}) {
if kit.Int(value["next"]) <= stamp {
m.Logs(EVENT, TIMER, key, kit.MDB_TIME, value["next"])
value["next"] = stamp + int(kit.Duration(value["interval"]))/int(time.Second)
m.Cmd(value["cmd"])
m.Grow(TIMER, nil, map[string]interface{}{
"create_time": kit.Format(t), "interval": value["interval"],
"cmd": value["cmd"], "key": key,
})
}
})
case d, ok := <-f.d:
if !ok {
return true
}
// 异步事件
m.Logs(EVENT, d[0], d[1:])
m.Grows(EVENT, d[0], "", "", func(index int, value map[string]interface{}) {
m.Cmd(value["cmd"], d).Cost("event %v", d)
})
case <-f.t:
_timer_action(m.Spawn())
}
}
return true
@ -73,147 +45,37 @@ func (f *Frame) Close(m *ice.Message, arg ...string) bool {
}
const (
SYSTEM_INIT = "system.init"
SERVE_START = "serve.start"
SERVE_CLOSE = "serve.close"
SPACE_START = "space.start"
SPACE_CLOSE = "space.close"
DREAM_START = "dream.start"
DREAM_CLOSE = "dream.close"
USER_CREATE = "user.create"
CHAT_CREATE = "chat.create"
MISS_CREATE = "miss.create"
MIND_CREATE = "mind.create"
)
const (
INIT = "init"
AUTO = "auto"
MAKE = "make"
BEGIN = "begin"
END = "end"
OPEN = "open"
CLOSE = "close"
START = "start"
STOP = "stop"
RESTART = "restart"
)
const (
LISTEN = "listen"
ACTION = "action"
)
const (
ROUTINE = "routine"
SIGNAL = "signal"
TIMER = "timer"
EVENT = "event"
DEBUG = "debug"
)
const GDB = "gdb"
var Index = &ice.Context{Name: "gdb", Help: "事件模块",
Configs: map[string]*ice.Config{
ROUTINE: {Name: "routine", Help: "协程", Value: kit.Data()},
SIGNAL: {Name: "signal", Help: "信号器", Value: kit.Dict(
kit.MDB_META, kit.Dict("pid", "var/run/ice.pid"),
kit.MDB_LIST, kit.List(),
kit.MDB_HASH, kit.Dict(
"2", []interface{}{"exit", "1"},
"3", []interface{}{"exit", "0"},
"15", []interface{}{"exit", "1"},
// "20", []interface{}{"void"},
"30", []interface{}{"exit"},
"31", []interface{}{"exit", "1"},
// "28", []interface{}{"void"},
),
)},
TIMER: {Name: "timer", Help: "定时器", Value: kit.Data("tick", "100ms")},
EVENT: {Name: "event", Help: "触发器", Value: kit.Data()},
},
var Index = &ice.Context{Name: GDB, Help: "事件模块",
Commands: map[string]*ice.Command{
ice.CTX_INIT: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
if os.Getenv("ctx_mod") != "" {
m.Cmd(nfs.SAVE, kit.Select(m.Conf(SIGNAL, "meta.pid"),
m.Conf(cli.RUNTIME, "conf.ctx_pid")), m.Conf(cli.RUNTIME, "host.pid"))
}
// 进程标识
if f, ok := m.Target().Server().(*Frame); ok {
// 注册信号
f.s = make(chan os.Signal, ice.MOD_CHAN)
m.Richs(SIGNAL, nil, kit.MDB_FOREACH, func(key string, value string) {
m.Logs(LISTEN, key, value)
signal.Notify(f.s, syscall.Signal(kit.Int(key)))
})
// 启动心跳
f.t = time.Tick(kit.Duration(m.Cap(ice.CTX_STREAM, m.Conf(TIMER, "meta.tick"))))
// 分发事件
f.d = make(chan []string, ice.MOD_CHAN)
}
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(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.Load()
}},
ice.CTX_EXIT: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
if f, ok := m.Target().Server().(*Frame); ok {
// 停止心跳
close(f.s)
// 停止事件
close(f.d)
f.e <- true
}
m.Save(TIMER)
}},
ROUTINE: {Name: "routine hash auto", Help: "协程", Action: map[string]*ice.Action{
mdb.CREATE: {Name: "create", Help: "创建", Hand: func(m *ice.Message, arg ...string) {
m.Cmdy(mdb.INSERT, ROUTINE, "", mdb.LIST, arg)
}},
}, Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
m.Option(mdb.FIELDS, "time,fileline")
m.Cmdy(mdb.SELECT, ROUTINE, "", mdb.LIST, arg)
}},
SIGNAL: {Name: "signal", Help: "信号器", Action: map[string]*ice.Action{
LISTEN: {Name: "listen signal cmd...", Help: "监听事件", Hand: func(m *ice.Message, arg ...string) {
m.Rich(SIGNAL, arg[0], arg[1:])
}},
}, Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {}},
TIMER: {Name: "timer", Help: "定时器", Action: map[string]*ice.Action{
LISTEN: {Name: "listen delay interval cmd...", Help: "监听事件", Hand: func(m *ice.Message, arg ...string) {
m.Rich(TIMER, nil, kit.Dict(
"next", time.Now().Add(kit.Duration(arg[0])).Unix(),
"interval", arg[1], "cmd", arg[2:],
))
}},
}, Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {}},
EVENT: {Name: "event", Help: "触发器", Action: map[string]*ice.Action{
LISTEN: {Name: "listen event cmd...", Help: "监听事件", Hand: func(m *ice.Message, arg ...string) {
m.Grow(EVENT, arg[0], kit.Dict("cmd", arg[1:]))
m.Logs(LISTEN, arg[0], arg[1:])
}},
ACTION: {Name: "action event arg...", Help: "触发事件", Hand: func(m *ice.Message, arg ...string) {
if f, ok := m.Target().Server().(*Frame); ok {
m.Logs(ACTION, arg[0], arg[1:])
f.d <- arg
}
}},
}, Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {}},
DEBUG: {Name: "debug", Help: "调试器", Action: map[string]*ice.Action{
LISTEN: {Name: "listen event cmd...", Help: "监听事件", Hand: func(m *ice.Message, arg ...string) {
m.Grow(EVENT, arg[0], kit.Dict("cmd", arg[1:]))
m.Logs(LISTEN, arg[0], "cmd", arg[1:])
}},
ACTION: {Name: "action event arg...", Help: "触发事件", Hand: func(m *ice.Message, arg ...string) {
if f, ok := m.Target().Server().(*Frame); ok {
m.Logs(ACTION, arg[0], "arg", arg[1:])
f.d <- arg
}
}},
}, Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {}},
},
}
func init() { ice.Index.Register(Index, &Frame{}, SIGNAL, TIMER, EVENT, DEBUG) }
func init() {
ice.Index.Register(Index, &Frame{},
ROUTINE, SIGNAL, EVENT, TIMER,
)
}

7
base/gdb/gdb.shy Normal file
View File

@ -0,0 +1,7 @@
chapter "gdb"
field "协程池" routine
field "信号量" signal
field "事件流" event
field "定时器" timer

61
base/gdb/routine.go Normal file
View File

@ -0,0 +1,61 @@
package gdb
import (
ice "github.com/shylinux/icebergs"
"github.com/shylinux/icebergs/base/mdb"
kit "github.com/shylinux/toolkits"
"strings"
)
const (
INNER = "inner"
)
const ROUTINE = "routine"
func init() {
Index.Merge(&ice.Context{
Configs: map[string]*ice.Config{
ROUTINE: {Name: ROUTINE, Help: "协程池", Value: kit.Data()},
},
Commands: map[string]*ice.Command{
ROUTINE: {Name: "routine hash auto 清理", Help: "协程池", Action: map[string]*ice.Action{
mdb.CREATE: {Name: "create fileline status", Help: "创建", Hand: func(m *ice.Message, arg ...string) {
m.Cmdy(mdb.INSERT, ROUTINE, "", mdb.HASH, arg)
}},
mdb.MODIFY: {Name: "modify", Help: "编辑", Hand: func(m *ice.Message, arg ...string) {
m.Cmdy(mdb.MODIFY, ROUTINE, "", mdb.HASH, kit.MDB_HASH, m.Option(kit.MDB_HASH), arg)
}},
mdb.REMOVE: {Name: "remove", Help: "删除", Hand: func(m *ice.Message, arg ...string) {
m.Cmdy(mdb.DELETE, ROUTINE, "", mdb.HASH, kit.MDB_HASH, m.Option(kit.MDB_HASH))
}},
mdb.PRUNES: {Name: "prunes", Help: "清理", Hand: func(m *ice.Message, arg ...string) {
m.Option(mdb.FIELDS, "time,hash,status,fileline")
m.Cmdy(mdb.PRUNES, ROUTINE, "", mdb.HASH, kit.MDB_STATUS, STOP)
}},
INNER: {Name: "inner", Help: "源码", Hand: func(m *ice.Message, arg ...string) {
switch kit.Select("", arg, 0) {
case kit.SSH_RUN:
m.Cmdy(INNER, arg[1:])
default:
ls := kit.Split(m.Option("fileline"), ":")
switch kit.Split(ls[0], "/")[0] {
case "usr":
ls[0] = strings.TrimPrefix(ls[0], "usr/icebergs/")
case "icebergs":
ls[0] = strings.TrimPrefix(ls[0], "icebergs/")
}
m.PushPlugin(INNER, INNER, kit.SSH_RUN)
m.Push("args", kit.Format([]string{"usr/icebergs/", ls[0], ls[1]}))
}
}},
}, Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
m.Option(mdb.FIELDS, kit.Select("time,hash,status,fileline", mdb.DETAIL, len(arg) > 0))
m.Cmdy(mdb.SELECT, ROUTINE, "", mdb.HASH, kit.MDB_HASH, arg)
m.PushAction(INNER, mdb.REMOVE)
}},
},
}, nil)
}

58
base/gdb/signal.go Normal file
View File

@ -0,0 +1,58 @@
package gdb
import (
ice "github.com/shylinux/icebergs"
"github.com/shylinux/icebergs/base/mdb"
kit "github.com/shylinux/toolkits"
"os/signal"
"syscall"
)
func _signal_listen(m *ice.Message, s int, arg ...string) {
if f, ok := m.Target().Server().(*Frame); ok {
m.Cmdy(mdb.INSERT, SIGNAL, "", mdb.HASH, arg)
signal.Notify(f.s, syscall.Signal(s))
}
}
func _signal_action(m *ice.Message, s int) {
m.Option(mdb.FIELDS, "time,signal,name,cmd")
msg := m.Cmd(mdb.SELECT, SIGNAL, "", mdb.HASH, SIGNAL, s)
msg.Table(func(index int, value map[string]string, head []string) {
m.Cmdy(kit.Split(value[kit.SSH_CMD]))
})
}
const (
LISTEN = "listen"
ACTION = "action"
)
const SIGNAL = "signal"
func init() {
Index.Merge(&ice.Context{
Configs: map[string]*ice.Config{
SIGNAL: {Name: SIGNAL, Help: "信号器", Value: kit.Data(
kit.MDB_PATH, "var/run/ice.pid", kit.MDB_SHORT, SIGNAL,
)},
},
Commands: map[string]*ice.Command{
SIGNAL: {Name: "signal auto 监听", Help: "信号器", Action: map[string]*ice.Action{
LISTEN: {Name: "listen signal name cmd", Help: "监听", Hand: func(m *ice.Message, arg ...string) {
_signal_listen(m, kit.Int(m.Option(SIGNAL)), arg...)
}},
ACTION: {Name: "action signal", Help: "触发", Hand: func(m *ice.Message, arg ...string) {
_signal_action(m, kit.Int(m.Option(SIGNAL)))
}},
mdb.REMOVE: {Name: "remove", Help: "删除", Hand: func(m *ice.Message, arg ...string) {
m.Cmdy(mdb.DELETE, SIGNAL, "", mdb.HASH, SIGNAL, m.Option(SIGNAL))
}},
}, Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
m.Option(mdb.FIELDS, "time,signal,name,cmd")
m.Cmdy(mdb.SELECT, SIGNAL, "", mdb.HASH, SIGNAL, arg)
m.PushAction(ACTION, mdb.REMOVE)
m.Sort(SIGNAL)
}},
},
}, nil)
}

76
base/gdb/timer.go Normal file
View File

@ -0,0 +1,76 @@
package gdb
import (
ice "github.com/shylinux/icebergs"
"github.com/shylinux/icebergs/base/mdb"
kit "github.com/shylinux/toolkits"
"time"
)
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)
}
func _timer_action(m *ice.Message, arg ...string) {
now := time.Now().UnixNano()
m.Option(mdb.FIELDS, "time,hash,delay,interval,order,next,cmd")
m.Richs(TIMER, "", kit.MDB_FOREACH, func(key string, value map[string]interface{}) {
if value = kit.GetMeta(value); value[kit.MDB_STATUS] == STOP {
return
}
order := kit.Int(value["order"])
if n := kit.Time(kit.Format(value["next"])); now > n && order > 0 {
m.Logs(TIMER, "key", key, "order", order)
msg := m.Cmd(value[kit.SSH_CMD])
m.Grow(TIMER, kit.Keys(kit.MDB_HASH, key), kit.Dict("res", msg.Result()))
if value["order"] = kit.Format(order - 1); order > 1 {
value["next"] = msg.Time(value["interval"])
}
}
})
}
const TIMER = "timer"
func init() {
Index.Merge(&ice.Context{
Configs: map[string]*ice.Config{
TIMER: {Name: TIMER, Help: "定时器", Value: kit.Data("tick", "100ms")},
},
Commands: map[string]*ice.Command{
TIMER: {Name: "timer hash id auto 添加 清理", Help: "定时器", Action: map[string]*ice.Action{
mdb.CREATE: {Name: "create delay=10ms interval=10s order=3 cmd=runtime", Help: "添加", Hand: func(m *ice.Message, arg ...string) {
_timer_create(m, arg...)
}},
mdb.MODIFY: {Name: "modify", Help: "编辑", Hand: func(m *ice.Message, arg ...string) {
m.Cmdy(mdb.MODIFY, TIMER, "", mdb.HASH, kit.MDB_HASH, m.Option(kit.MDB_HASH), arg)
}},
mdb.REMOVE: {Name: "remove", Help: "删除", Hand: func(m *ice.Message, arg ...string) {
m.Cmdy(mdb.DELETE, TIMER, "", mdb.HASH, kit.MDB_HASH, m.Option(kit.MDB_HASH))
}},
mdb.PRUNES: {Name: "prunes", Help: "清理", Hand: func(m *ice.Message, arg ...string) {
m.Option(mdb.FIELDS, "time,hash,delay,interval,order,next,cmd")
m.Cmdy(mdb.PRUNES, TIMER, "", mdb.HASH, "order", 0)
}},
ACTION: {Name: "action", Help: "执行", Hand: func(m *ice.Message, arg ...string) {
_timer_action(m, arg...)
}},
}, Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
if len(arg) == 0 {
m.Option(mdb.FIELDS, kit.Select("time,hash,delay,interval,order,next,cmd", mdb.DETAIL, len(arg) > 0))
m.Cmdy(mdb.SELECT, TIMER, "", mdb.HASH, kit.MDB_HASH, arg)
m.PushAction(mdb.REMOVE)
return
}
m.Option(mdb.FIELDS, kit.Select("time,id,res", mdb.DETAIL, len(arg) > 1))
m.Cmdy(mdb.SELECT, TIMER, kit.Keys(kit.MDB_HASH, arg[0]), mdb.LIST, kit.MDB_ID, arg[1:])
return
}},
},
}, nil)
}

View File

@ -9,8 +9,12 @@ import (
"os"
"path"
"sort"
"strings"
)
func _fields(m *ice.Message) []string {
return kit.Split(kit.Select("time,hash,type,name,text", strings.Join(kit.Simple(m.Optionv(FIELDS)), ",")))
}
func _file_name(m *ice.Message, arg ...string) string {
return kit.Select(path.Join("usr/export", path.Join(arg[:2]...)), arg, 3)
}
@ -29,7 +33,7 @@ func _hash_select(m *ice.Message, prefix, chain, field, value string) {
if field == kit.MDB_HASH && value == RANDOM {
value = kit.MDB_RANDOMS
}
fields := kit.Split(kit.Select("time,hash,type,name,text", m.Option(FIELDS)))
fields := _fields(m)
m.Richs(prefix, chain, value, func(key string, val map[string]interface{}) {
if val[kit.MDB_META] != nil {
val = val[kit.MDB_META].(map[string]interface{})

View File

@ -17,60 +17,6 @@ import (
"time"
)
type item struct {
c chan []byte
last []byte
}
func (i item) Read(buf []byte) (int, error) {
b := <-i.c
n := copy(buf, b)
return n, nil
}
type tmux struct {
input io.Reader
waits []chan []byte
}
func (t *tmux) get() *item {
c := make(chan []byte)
t.waits = append(t.waits, c)
return &item{c: c}
}
func (t *tmux) loop() {
buf := make([]byte, 1024)
for {
n, e := t.input.Read(buf)
if e != nil {
break
}
if len(t.waits) > 0 {
wait := t.waits[len(t.waits)-1]
wait <- buf[:n]
}
}
}
func (t *tmux) read(cb func(buf []byte)) {
c := make(chan []byte)
t.waits = append(t.waits, c)
go func() {
for {
cb(<-c)
}
}()
return
}
func (t *tmux) over() {
if len(t.waits) > 0 {
t.waits = t.waits[:len(t.waits)-1]
}
}
var stdin = &tmux{input: os.Stdin}
func init() { go stdin.loop() }
func Render(msg *ice.Message, cmd string, args ...interface{}) {
defer func() { msg.Log_EXPORT(mdb.RENDER, cmd, kit.MDB_TEXT, args) }()
@ -287,7 +233,6 @@ func (f *Frame) scan(m *ice.Message, h, line string, r io.Reader) *Frame {
f.ps2 = kit.Simple(m.Confv("prompt", "meta.PS2"))
ps := f.ps1
f.count = 1
m.I, m.O = r, f.stdout
bio := bufio.NewScanner(r)
for f.prompt(m, ps...); bio.Scan() && !f.exit; f.prompt(m, ps...) {
@ -295,6 +240,9 @@ func (f *Frame) scan(m *ice.Message, h, line string, r io.Reader) *Frame {
f.count++
if len(bio.Text()) == 0 {
if h == STDIO {
f.count--
}
continue // 空行
}
if strings.HasSuffix(bio.Text(), "\\") {
@ -332,8 +280,7 @@ func (f *Frame) Start(m *ice.Message, arg ...string) bool {
var r io.Reader
switch m.Cap(ice.CTX_STREAM, f.source) {
case STDIO: // 终端交互
// r, f.stdout = os.Stdin, os.Stdout
r, f.stdout = stdin.get(), os.Stdout
r, f.stdout = os.Stdin, os.Stdout
m.Option("_option", ice.MSG_USERNAME)
m.Option(ice.MSG_USERNAME, cli.UserName)
@ -359,7 +306,8 @@ func (f *Frame) Start(m *ice.Message, arg ...string) bool {
return true
}
if f.source == STDIO {
if f.count = 1; f.source == STDIO {
f.count = kit.Int(m.Conf(SOURCE, "hash.stdio.meta.count")) + 1
f.scan(m, STDIO, "", r)
} else {
h := m.Cmdx(mdb.INSERT, SOURCE, "", mdb.HASH, kit.MDB_NAME, f.source)

View File

@ -201,11 +201,22 @@ func init() {
mdb.PRUNES: {Name: "prunes", Help: "清理", Hand: func(m *ice.Message, arg ...string) {
m.Cmdy(mdb.PRUNES, SERVICE, "", mdb.HASH, kit.MDB_STATUS, tcp.CLOSE)
}},
mdb.INVITE: {Name: "invite", Help: "邀请", Hand: func(m *ice.Message, arg ...string) {
u := kit.ParseURL(m.Option(ice.MSG_USERWEB))
m.Option("hostname", strings.Split(u.Host, ":")[0])
m.Option("_process", "_inner")
if buf, err := kit.Render(`
ssh {{.Option "user.name"}}@{{.Option "hostname"}} -p {{.Option "port"}}
`, m); err == nil {
m.Cmdy("web.wiki.spark", "shell", string(buf))
}
}},
}, Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
if len(arg) == 0 {
m.Option(mdb.FIELDS, "time,status,port,private,auth,count")
m.Cmdy(mdb.SELECT, SERVICE, "", mdb.HASH)
m.PushAction("导入,添加,导出")
m.PushAction(mdb.IMPORT, mdb.INSERT, mdb.EXPORT, mdb.INVITE)
return
}

View File

@ -95,9 +95,8 @@ func init() {
value = kit.GetMeta(value)
input := value["input"].(io.Writer)
stdin.read(func(buf []byte) {
_watch(m, os.Stdin, input, func(buf []byte) {
m.Debug("input %v", string(buf))
input.Write(buf)
})
output := value["output"].(io.Reader)

View File

@ -17,6 +17,10 @@ import (
)
const LOGIN = "_login"
const (
SERVE_START = "serve.start"
SERVE_CLOSE = "serve.close"
)
func _serve_login(msg *ice.Message, cmds []string, w http.ResponseWriter, r *http.Request) ([]string, bool) {
msg.Option(ice.MSG_USERNAME, "")

View File

@ -5,7 +5,6 @@ import (
"github.com/shylinux/icebergs/base/aaa"
"github.com/shylinux/icebergs/base/cli"
"github.com/shylinux/icebergs/base/ctx"
"github.com/shylinux/icebergs/base/gdb"
"github.com/shylinux/icebergs/base/mdb"
"github.com/shylinux/icebergs/base/tcp"
kit "github.com/shylinux/toolkits"
@ -78,9 +77,9 @@ func (web *Frame) Start(m *ice.Message, arg ...string) bool {
web.m, web.Server = m, &http.Server{Handler: web}
m.Option(tcp.LISTEN_CB, func(l net.Listener) {
m.Event(gdb.SERVE_START, arg[0])
m.Event(SERVE_START, arg[0])
m.Warn(true, "listen %s", web.Server.Serve(l))
m.Event(gdb.SERVE_CLOSE, arg[0])
m.Event(SERVE_CLOSE, arg[0])
})
ls := strings.Split(m.Cap(ice.CTX_STREAM, client["hostname"]), ":")

View File

@ -5,6 +5,7 @@ const ( //MOD
MOD_FILE = 0640
MOD_CHAN = 16
MOD_TICK = "1s"
MOD_BUF = 1024
MOD_DATE = "2006-01-02"

19
exec.go
View File

@ -109,11 +109,11 @@ func (m *Message) Back(res *Message) *Message {
}
return m
}
func (m *Message) Gos(msg *Message, cb interface{}) *Message {
m.Cmd("gdb.routine", "create", "fileline", kit.FileLine(cb, 3))
task.Put(nil, func(task *task.Task) error {
func (m *Message) Gos(msg *Message, cb interface{}, args ...interface{}) *Message {
task.Put(m.Cmdx("gdb.routine", "create", "fileline", kit.FileLine(cb, 3), "status", "start"), func(task *task.Task) error {
msg.Optionv("task.hash", task.Arg)
msg.Optionv("_task", task)
msg.TryCatch(msg, true, func(msg *Message) {
switch cb := cb.(type) {
case func(*Message):
@ -122,16 +122,17 @@ func (m *Message) Gos(msg *Message, cb interface{}) *Message {
cb()
}
})
msg.Option(kit.MDB_HASH, task.Arg)
msg.Cmdx("gdb.routine", "modify", "status", "stop")
return nil
})
return m
}
func (m *Message) Go(cb interface{}) *Message {
func (m *Message) Go(cb interface{}, args ...interface{}) *Message {
switch cb := cb.(type) {
case func(*Message):
return m.Gos(m.Spawn(), cb)
case func():
return m.Gos(m, cb)
return m.Gos(m.Spawn(), cb, args...)
}
return m.Gos(m, cb)
return m.Gos(m, cb, args...)
}

19
go.sum
View File

@ -0,0 +1,19 @@
github.com/google/uuid v1.1.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/kr/pty v1.1.1 h1:VkoXIwSboBpnk99O/KFauAEILuNHv5DVFKZMBN/gUgw=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/maruel/rs v0.0.0-20150922171536-2c81c4312fe4/go.mod h1:kcRFpEzolcEklV6rD7W95mG49/sbdX/PlFmd7ni3RvA=
github.com/nareix/joy4 v0.0.0-20200507095837-05a4ffbb5369/go.mod h1:aFJ1ZwLjvHN4yEzE5Bkz8rD8/d8Vlj3UIuvz2yfET7I=
github.com/shylinux/toolkits v0.1.8 h1:Lh5HkR1aRzhOOVu9eHwZ5y7dfW7hcFy29IR5tQ5qUeM=
github.com/shylinux/toolkits v0.1.8/go.mod h1:Y68Ot6xOmo1bun67YvqC3chDGeU2gDxtsUnvVDGJm4g=
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e h1:MRM5ITcdelLK2j1vwZ3Je0FKVCfqOLp5zO6trqMLYs0=
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e/go.mod h1:XV66xRDqSt+GTGFMVlhk3ULuV0y9ZmzeVGR4mloJI3M=
github.com/tuotoo/qrcode v0.0.0-20190222102259-ac9c44189bf2/go.mod h1:lPnW9HVS0vJdeYyQtOvIvlXgZPNhUAhwz+z5r8AJk0Y=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550 h1:ObdrDkeb4kJdCP557AjRjq69pTHfNouLtWZG7j9rPN8=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=

16
misc.go
View File

@ -37,11 +37,11 @@ func (m *Message) Watch(key string, arg ...string) *Message {
if len(arg) == 0 {
arg = append(arg, m.Prefix("auto"))
}
m.Cmd("gdb.event", "listen", key, arg)
m.Cmd("gdb.event", "listen", "event", key, "cmd", strings.Join(arg, " "))
return m
}
func (m *Message) Event(key string, arg ...string) *Message {
m.Cmd("gdb.event", "action", key, arg)
m.Cmd("gdb.event", "action", "event", key, strings.Join(arg, " "))
return m
}
func (m *Message) Right(arg ...interface{}) bool {
@ -75,10 +75,8 @@ func (m *Message) PushRender(key, view, name string, arg ...string) *Message {
case "button":
list := []string{}
for _, k := range kit.Split(name) {
list = append(list, fmt.Sprintf(`<input type="button" value="%s">`, k))
}
for _, k := range arg {
list = append(list, fmt.Sprintf(`<input type="button" value="%s">`, k))
list = append(list, fmt.Sprintf(`<input type="button" name="%s" value="%s">`,
k, kit.Select(k, kit.Value(m.cmd.Meta, kit.Keys("trans", k)))))
}
m.Push(key, strings.Join(list, ""))
case "video":
@ -105,6 +103,12 @@ func (m *Message) PushAction(list ...interface{}) {
func (m *Message) PushButton(key string, arg ...string) {
m.PushRender("action", "button", key, arg...)
}
func (m *Message) PushPlugin(key string, arg ...string) *Message {
m.Option("_process", "_field")
m.Option("_prefix", arg)
m.Cmdy("command", key)
return m
}
func (m *Message) PushDetail(value interface{}, arg ...interface{}) *Message {
return m.Push("detail", value, arg...)
}

View File

@ -5,7 +5,6 @@ import (
"github.com/shylinux/icebergs/base/cli"
"github.com/shylinux/icebergs/base/mdb"
"github.com/shylinux/icebergs/base/nfs"
"github.com/shylinux/icebergs/base/web"
kit "github.com/shylinux/toolkits"
"os"
@ -148,35 +147,37 @@ func init() {
}},
}, Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
m.Richs(REPOS, nil, kit.Select(kit.MDB_FOREACH, arg, 0), func(key string, value map[string]interface{}) {
if m.Option(cli.CMD_DIR, kit.Value(value, "meta.path")); len(arg) > 0 {
// 更改详情
value = kit.GetMeta(value)
if m.Option(cli.CMD_DIR, value[kit.MDB_PATH]); len(arg) > 0 {
m.Echo(m.Cmdx(cli.SYSTEM, GIT, "diff"))
return
return // 更改详情
}
// 更改列表
for _, v := range strings.Split(strings.TrimSpace(m.Cmdx(cli.SYSTEM, GIT, "status", "-sb")), "\n") {
vs := strings.SplitN(strings.TrimSpace(v), " ", 2)
m.Push("name", kit.Value(value, "meta.name"))
m.Push("name", value[kit.MDB_NAME])
m.Push("tags", vs[0])
m.Push("file", vs[1])
list := []string{}
switch vs[0] {
case "##":
if strings.Contains(vs[1], "ahead") {
list = append(list, m.Cmdx(mdb.RENDER, web.RENDER.Button, "上传"))
list = append(list, "上传")
}
default:
if strings.Contains(vs[0], "??") {
list = append(list, m.Cmdx(mdb.RENDER, web.RENDER.Button, "添加"))
list = append(list, "添加")
} else {
list = append(list, m.Cmdx(mdb.RENDER, web.RENDER.Button, "提交"))
list = append(list, "提交")
}
}
m.Push("action", strings.Join(list, ""))
m.PushButton(strings.Join(list, ","))
}
})
m.Sort("name")
m.Sort(kit.MDB_NAME)
}},
},
}, nil)

View File

@ -86,22 +86,22 @@ var Index = &ice.Context{Name: TMUX, Help: "工作台",
}
}},
mdb.EXPORT: {Name: "export", Help: "导出", Hand: func(m *ice.Message, arg ...string) {
m.Conf(BUFFER, mdb.LIST, "")
m.Conf(BUFFER, kit.Keys(mdb.META, "count"), "0")
m.Conf(m.Prefix(BUFFER), mdb.LIST, "")
m.Conf(m.Prefix(BUFFER), kit.Keys(mdb.META, "count"), "0")
m.Cmd(BUFFER).Table(func(index int, value map[string]string, head []string) {
m.Grow(BUFFER, "", kit.Dict(
m.Cmd(m.Prefix(BUFFER)).Table(func(index int, value map[string]string, head []string) {
m.Grow(m.Prefix(BUFFER), "", kit.Dict(
"name", value[head[0]], "text", m.Cmdx(cli.SYSTEM, TMUX, "show-buffer", "-b", value[head[0]]),
))
})
m.Cmdy(mdb.EXPORT, m.Prefix(BUFFER), "", mdb.LIST)
}},
mdb.IMPORT: {Name: "import", Help: "导入", Hand: func(m *ice.Message, arg ...string) {
m.Conf(BUFFER, mdb.LIST, "")
m.Conf(BUFFER, kit.Keys(mdb.META, "count"), "0")
m.Conf(m.Prefix(BUFFER), mdb.LIST, "")
m.Conf(m.Prefix(BUFFER), kit.Keys(mdb.META, "count"), "0")
m.Cmdy(mdb.IMPORT, m.Prefix(BUFFER), "", mdb.LIST)
m.Grows(BUFFER, "", "", "", func(index int, value map[string]interface{}) {
m.Grows(m.Prefix(BUFFER), "", "", "", func(index int, value map[string]interface{}) {
m.Cmd(cli.SYSTEM, TMUX, "set-buffer", "-b", value["name"], value["text"])
})
}},
@ -145,7 +145,7 @@ var Index = &ice.Context{Name: TMUX, Help: "工作台",
m.Cmdy(mdb.IMPORT, m.Prefix(SCRIPT), "", mdb.HASH)
}},
}, Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
if m.Option(mdb.FIELDS, m.Conf(SCRIPT, kit.META_FIELD)); len(arg) > 0 {
if m.Option(mdb.FIELDS, m.Conf(m.Prefix(SCRIPT), kit.META_FIELD)); len(arg) > 0 {
m.Option(mdb.FIELDS, mdb.DETAIL)
}
m.Cmdy(mdb.SELECT, m.Prefix(SCRIPT), "", mdb.HASH, kit.MDB_NAME, arg)
@ -232,13 +232,13 @@ var Index = &ice.Context{Name: TMUX, Help: "工作台",
if len(arg) == 0 {
// 会话列表
m.Split(m.Cmdx(cli.SYSTEM, TMUX, "list-session", "-F", m.Conf(cmd, "meta.format")), m.Conf(cmd, "meta.fields"), ",", "\n")
m.Split(m.Cmdx(cli.SYSTEM, TMUX, "list-session", "-F", m.Conf(m.Prefix(cmd), "meta.format")), m.Conf(m.Prefix(cmd), "meta.fields"), ",", "\n")
m.Table(func(index int, value map[string]string, head []string) {
switch value["tag"] {
case "1":
m.PushRender("action", "button", "")
m.PushButton("")
default:
m.PushRender("action", "button", "进入", "删除")
m.PushButton("进入", "删除")
}
})
return
@ -260,11 +260,11 @@ var Index = &ice.Context{Name: TMUX, Help: "工作台",
}},
WINDOW: {Name: "windows", Help: "窗口", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
m.Split(m.Cmdx(cli.SYSTEM, TMUX, "list-windows", "-t", kit.Select("", arg, 0),
"-F", m.Conf(cmd, "meta.format")), m.Conf(cmd, "meta.fields"), ",", "\n")
"-F", m.Conf(m.Prefix(cmd), "meta.format")), m.Conf(m.Prefix(cmd), "meta.fields"), ",", "\n")
}},
PANE: {Name: "panes", Help: "终端", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
m.Split(m.Cmdx(cli.SYSTEM, TMUX, "list-panes", "-t", kit.Select("", arg, 0),
"-F", m.Conf(cmd, "meta.format")), m.Conf(cmd, "meta.fields"), ",", "\n")
"-F", m.Conf(m.Prefix(cmd), "meta.format")), m.Conf(m.Prefix(cmd), "meta.fields"), ",", "\n")
}},
VIEW: {Name: "view", Help: "终端", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
m.Cmdy(cli.SYSTEM, TMUX, "capture-pane", "-pt", kit.Select("", arg, 0)).Set(ice.MSG_APPEND)

15
type.go
View File

@ -87,7 +87,7 @@ func (c *Context) _hand(m *Message, cmd *Command, key string, k string, h *Actio
for _, v := range h.List {
name := kit.Format(kit.Value(v, "name"))
value := kit.Format(kit.Value(v, "value"))
m.Option(name, value)
m.Option(name, kit.Select("", value, !strings.HasPrefix(value, "@")))
}
for i := 0; i < len(arg)-1; i += 2 {
m.Option(arg[i], arg[i+1])
@ -101,6 +101,7 @@ func (c *Context) cmd(m *Message, cmd *Command, key string, arg ...string) *Mess
return m
}
m.cmd = cmd
if m.Hand = true; len(arg) > 1 && arg[0] == "action" && cmd.Action != nil {
if h, ok := cmd.Action[arg[1]]; ok {
return c._hand(m, cmd, key, arg[1], h, arg[2:]...)
@ -176,6 +177,7 @@ func (c *Context) Merge(s *Context, x Server) *Context {
}
for k, a := range v.Action {
kit.Value(v.Meta, kit.Keys("trans", k), a.Help)
if a.List == nil {
a.List = c._split(a.Name)
}
@ -287,7 +289,13 @@ func (c *Context) Start(m *Message, arg ...string) bool {
m.Hold(1)
wait := make(chan bool)
m.Gos(m, func(m *Message) {
var p interface{}
if c.server != nil {
p = c.server.Start
}
m.Go(func() {
m.Log(LOG_START, c.Cap(CTX_FOLLOW))
c.Cap(CTX_STATUS, CTX_START)
@ -298,7 +306,7 @@ func (c *Context) Start(m *Message, arg ...string) bool {
if m.Done(); m.wait != nil {
m.wait <- true
}
})
}, p)
<-wait
return true
}
@ -327,6 +335,7 @@ type Message struct {
source *Context
target *Context
cmd *Command
cb func(*Message) *Message
W http.ResponseWriter