1
0
forked from x/icebergs

mix github

This commit is contained in:
shylinux 2019-12-29 19:02:18 +08:00
commit 3bf7b015df
22 changed files with 549 additions and 229 deletions

View File

@ -16,6 +16,7 @@ var Index = &ice.Context{Name: "aaa", Help: "认证模块",
Commands: map[string]*ice.Command{
ice.ICE_INIT: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
m.Cmd(ice.CTX_CONFIG, "load", "aaa.json")
// 权限索引
m.Conf(ice.AAA_ROLE, "black.tech.meta.short", "chain")
m.Conf(ice.AAA_ROLE, "white.tech.meta.short", "chain")
m.Conf(ice.AAA_ROLE, "black.void.meta.short", "chain")
@ -24,16 +25,19 @@ var Index = &ice.Context{Name: "aaa", Help: "认证模块",
ice.ICE_EXIT: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
m.Cmd(ice.CTX_CONFIG, "save", "aaa.json", ice.AAA_ROLE, ice.AAA_USER, ice.AAA_SESS)
}},
ice.AAA_ROLE: {Name: "role", Help: "角色", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
switch arg[0] {
case "check":
// 用户角色
m.Echo(kit.Select("void", "root", arg[1] == m.Conf(ice.CLI_RUNTIME, "boot.username")))
case "black", "white":
// 黑白名单
m.Rich(ice.AAA_ROLE, kit.Keys(arg[0], arg[1]), kit.Dict(
"chain", kit.Keys(arg[3:]),
"status", arg[2],
"status", arg[2], "chain", kit.Keys(arg[3:]),
))
m.Log(ice.LOG_ENABLE, "role: %s %s: %v", arg[1], arg[0], arg[3:])
case "right":
if m.Option(ice.MSG_USERROLE) == ice.ROLE_ROOT {
@ -53,7 +57,7 @@ var Index = &ice.Context{Name: "aaa", Help: "认证模块",
ok = value["status"] != "enable"
})
}
if m.Warn(!ok, "no right %s", keys) {
if m.Warn(!ok, "black right %s", keys) {
break
}
if m.Option(ice.MSG_USERROLE) == ice.ROLE_TECH {
@ -63,19 +67,16 @@ var Index = &ice.Context{Name: "aaa", Help: "认证模块",
}
ok = false
keys = strings.Split(kit.Keys(arg[2:]), ".")
m.Info("keys: %s", keys)
for i := 0; i < len(keys); i++ {
if ok {
break
}
// 白名单
m.Richs(ice.AAA_ROLE, kit.Keys("white", arg[1]), kit.Keys(keys[:i+1]), func(key string, value map[string]interface{}) {
m.Info("value: %s", value)
ok = value["status"] == "enable"
})
}
if m.Warn(!ok, "no right %s", keys) {
if m.Warn(!ok, "no white right %s", keys) {
break
}
// 普通用户
@ -88,6 +89,7 @@ var Index = &ice.Context{Name: "aaa", Help: "认证模块",
// 用户认证
user := m.Richs(ice.AAA_USER, nil, arg[1], nil)
if user == nil {
// 创建用户
m.Rich(ice.AAA_USER, nil, kit.Dict(
"username", arg[1], "password", arg[2],
"usernode", m.Conf(ice.CLI_RUNTIME, "boot.hostname"),
@ -95,20 +97,25 @@ var Index = &ice.Context{Name: "aaa", Help: "认证模块",
user = m.Richs(ice.AAA_USER, nil, arg[1], nil)
m.Info("create user: %s %s", arg[1], kit.Format(user))
m.Event(ice.USER_CREATE, arg[1])
} else if kit.Format(user["password"]) != arg[2] {
// 认证失败
m.Info("login fail user: %s", arg[1])
break
}
// 用户授权
sessid := kit.Format(user[ice.WEB_SESS])
if sessid == "" {
if m.Options(ice.MSG_SESSID) && m.Cmdx(ice.AAA_SESS, "check", m.Option(ice.MSG_SESSID)) == arg[1] {
// 复用会话
m.Echo(m.Option(ice.MSG_SESSID))
break
}
// 创建会话
role := m.Cmdx(ice.AAA_ROLE, "check", arg[1])
sessid = m.Rich(ice.AAA_SESS, nil, kit.Dict(
sessid := m.Rich(ice.AAA_SESS, nil, kit.Dict(
"username", arg[1], "userrole", role,
))
m.Info("user: %s role: %s sess: %s", arg[1], role, sessid)
}
m.Echo(sessid)
}
}},

View File

@ -17,17 +17,24 @@ var Index = &ice.Context{Name: "cli", Help: "命令模块",
Caches: map[string]*ice.Cache{},
Configs: map[string]*ice.Config{
ice.CLI_RUNTIME: {Name: "runtime", Help: "运行环境", Value: kit.Dict()},
ice.CLI_SYSTEM: {Name: "system", Help: "系统命令", Value: kit.Data()},
},
Commands: map[string]*ice.Command{
ice.ICE_INIT: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
m.Cmd(ice.CTX_CONFIG, "load", "cli.json")
m.Conf(ice.CLI_RUNTIME, "host.ctx_self", os.Getenv("ctx_self"))
m.Conf(ice.CLI_RUNTIME, "host.ctx_dev", os.Getenv("ctx_dev"))
// 启动配置
m.Conf(ice.CLI_RUNTIME, "conf.ctx_self", os.Getenv("ctx_self"))
m.Conf(ice.CLI_RUNTIME, "conf.ctx_dev", os.Getenv("ctx_dev"))
m.Conf(ice.CLI_RUNTIME, "conf.ctx_shy", os.Getenv("ctx_shy"))
m.Conf(ice.CLI_RUNTIME, "conf.ctx_pid", os.Getenv("ctx_pid"))
// 主机信息
m.Conf(ice.CLI_RUNTIME, "host.GOARCH", runtime.GOARCH)
m.Conf(ice.CLI_RUNTIME, "host.GOOS", runtime.GOOS)
m.Conf(ice.CLI_RUNTIME, "host.pid", os.Getpid())
// 启动信息
if name, e := os.Hostname(); e == nil {
m.Conf(ice.CLI_RUNTIME, "boot.hostname", kit.Select(name, os.Getenv("HOSTNAME")))
}
@ -37,18 +44,21 @@ var Index = &ice.Context{Name: "cli", Help: "命令模块",
if name, e := os.Getwd(); e == nil {
m.Conf(ice.CLI_RUNTIME, "boot.pathname", path.Base(kit.Select(name, os.Getenv("PWD"))))
}
m.Conf(ice.CLI_RUNTIME, "boot.time", m.Time())
// 启动记录
count := m.Confi(ice.CLI_RUNTIME, "boot.count") + 1
m.Conf(ice.CLI_RUNTIME, "boot.count", count)
m.Conf(ice.CLI_RUNTIME, "node.type", kit.MIME_WORKER)
// 节点信息
m.Conf(ice.CLI_RUNTIME, "node.time", m.Time())
m.Conf(ice.CLI_RUNTIME, "node.type", ice.WEB_WORKER)
m.Conf(ice.CLI_RUNTIME, "node.name", m.Conf(ice.CLI_RUNTIME, "boot.pathname"))
m.Log("info", "runtime %v", kit.Formats(m.Confv(ice.CLI_RUNTIME)))
}},
ice.ICE_EXIT: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
m.Cmd(ice.CTX_CONFIG, "save", "cli.json", ice.CLI_RUNTIME)
m.Cmd(ice.CTX_CONFIG, "save", "cli.json", ice.CLI_RUNTIME, ice.CLI_SYSTEM)
}},
ice.CLI_RUNTIME: {Name: "runtime", Help: "运行环境", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
}},
ice.CLI_SYSTEM: {Name: "system", Help: "系统命令", Hand: func(m *ice.Message, c *ice.Context, key string, arg ...string) {
@ -56,16 +66,21 @@ var Index = &ice.Context{Name: "cli", Help: "命令模块",
// 运行目录
cmd.Dir = m.Option("cmd_dir")
if len(cmd.Dir) > 0 {
m.Info("dir: %s", cmd.Dir)
}
// 环境变量
env := kit.Simple(m.Optionv("cmd_env"))
for i := 0; i < len(env)-1; i += 2 {
cmd.Env = append(cmd.Env, fmt.Sprintf("%s=%s", env[i], env[i+1]))
}
if len(cmd.Env) > 0 {
m.Info("env: %s", cmd.Env)
}
if m.Option("cmd_type") == "daemon" {
switch m.Option("cmd_type") {
case "daemon":
// 守护进程
m.Gos(m, func(m *ice.Message) {
if e := cmd.Start(); e != nil {
@ -73,10 +88,10 @@ var Index = &ice.Context{Name: "cli", Help: "命令模块",
} else if e := cmd.Wait(); e != nil {
m.Warn(e != nil, "%v wait: %s", arg, e)
} else {
m.Info("%v exit", arg)
m.Cost("%v exit: %v", arg, cmd.ProcessState.ExitCode())
}
})
} else {
default:
// 系统命令
out := bytes.NewBuffer(make([]byte, 0, 1024))
err := bytes.NewBuffer(make([]byte, 0, 1024))
@ -85,9 +100,10 @@ var Index = &ice.Context{Name: "cli", Help: "命令模块",
if e := cmd.Run(); e != nil {
m.Warn(e != nil, "%v run: %s", arg, kit.Select(e.Error(), err.String()))
} else {
m.Echo(out.String())
m.Cost("%v exit: %v", arg, cmd.ProcessState.ExitCode())
}
m.Push("code", int(cmd.ProcessState.ExitCode()))
m.Echo(out.String())
}
}},
},

View File

@ -79,7 +79,7 @@ var Index = &ice.Context{Name: "ctx", Help: "元始模块",
}},
ice.CTX_CONFIG: {Name: "config", Help: "配置", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
if len(arg) == 0 {
m.Travel(func(p *ice.Context, s *ice.Context, key string, conf *ice.Config) {
ice.Pulse.Travel(func(p *ice.Context, s *ice.Context, key string, conf *ice.Config) {
m.Push("key", key)
m.Push("name", conf.Name)
m.Push("value", kit.Format(conf.Value))

View File

@ -29,7 +29,7 @@ func (f *Frame) Start(m *ice.Message, arg ...string) bool {
if !ok {
return true
}
m.Info("%s: %v", ice.GDB_SIGNAL, s)
m.Log(ice.LOG_SIGNAL, "%v: %v", s, m.Confv(ice.GDB_SIGNAL, kit.Keys(kit.MDB_HASH, s)))
m.Cmd(m.Confv(ice.GDB_SIGNAL, kit.Keys(kit.MDB_HASH, s)))
case t, ok := <-f.t:
@ -54,7 +54,7 @@ func (f *Frame) Start(m *ice.Message, arg ...string) bool {
if !ok {
return true
}
m.Info("%s: %v", ice.GDB_EVENT, d)
m.Log(ice.LOG_EVENTS, "%s: %v", d[0], d[1:])
m.Grows(ice.GDB_EVENT, d[0], "", "", func(index int, value map[string]interface{}) {
m.Cmd(value["cmd"], d[1:]).Cost("event %v", d)
})
@ -69,66 +69,73 @@ func (f *Frame) Close(m *ice.Message, arg ...string) bool {
var Index = &ice.Context{Name: "gdb", Help: "事件模块",
Caches: map[string]*ice.Cache{},
Configs: map[string]*ice.Config{
ice.GDB_SIGNAL: {Name: "signal", Help: "信号器", Value: map[string]interface{}{
kit.MDB_META: map[string]interface{}{
"pid": "var/run/shy.pid",
},
kit.MDB_HASH: map[string]interface{}{
"2": []interface{}{"exit"},
"3": []interface{}{"exit", "1"},
"15": []interface{}{"exit"},
"30": []interface{}{"exit"},
"31": []interface{}{"exit", "1"},
"28": "WINCH",
},
kit.MDB_LIST: map[string]interface{}{},
}},
ice.GDB_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"},
"3", []interface{}{"exit", "1"},
"15", []interface{}{"exit"},
"30", []interface{}{"exit"},
"31", []interface{}{"exit", "1"},
"28", "WINCH",
),
)},
ice.GDB_TIMER: {Name: "timer", Help: "定时器", Value: kit.Data("tick", "100ms")},
ice.GDB_EVENT: {Name: "event", Help: "触发器", Value: kit.Data()},
},
Commands: map[string]*ice.Command{
ice.ICE_INIT: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
if f, p, e := kit.Create(m.Conf(ice.GDB_SIGNAL, kit.Keys(kit.MDB_META, "pid"))); m.Assert(e) {
defer f.Close()
f.WriteString(kit.Format(os.Getpid()))
m.Log("info", "pid %d: %s", os.Getpid(), p)
}
// 进程标识
m.Cmd("nfs.save", kit.Select(m.Conf(ice.GDB_SIGNAL, "meta.pid"),
m.Conf(ice.CLI_RUNTIME, "conf.ctx_pid")), m.Conf(ice.CLI_RUNTIME, "host.pid"))
if f, ok := m.Target().Server().(*Frame); ok {
// 注册信号
f.s = make(chan os.Signal, ice.ICE_CHAN)
m.Confm(ice.GDB_SIGNAL, kit.MDB_HASH, func(sig string, action string) {
m.Log(ice.GDB_SIGNAL, "add %s: %s", sig, action)
signal.Notify(f.s, syscall.Signal(kit.Int(sig)))
m.Richs(ice.GDB_SIGNAL, nil, "*", func(key string, value string) {
m.Log(ice.LOG_LISTEN, "%s: %s", key, value)
signal.Notify(f.s, syscall.Signal(kit.Int(key)))
})
f.t = time.Tick(kit.Duration(m.Cap(ice.CTX_STREAM, m.Conf(ice.GDB_TIMER, kit.Keys(kit.MDB_META, "tick")))))
// 启动心跳
f.t = time.Tick(kit.Duration(m.Cap(ice.CTX_STREAM, m.Conf(ice.GDB_TIMER, "meta.tick"))))
// 分发事件
f.d = make(chan []string, ice.ICE_CHAN)
}
}},
ice.ICE_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)
}
}},
ice.GDB_SIGNAL: {Name: "signal", Help: "信号器", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
m.Conf(ice.GDB_SIGNAL, kit.Keys(kit.MDB_META, arg[0]), arg[1:])
switch arg[0] {
case "listen":
// 监听信号
m.Rich(ice.GDB_SIGNAL, arg[0], arg[1:])
}
}},
ice.GDB_TIMER: {Name: "timer", Help: "定时器", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
switch arg[0] {
case "start":
m.Rich(ice.GDB_TIMER, nil, map[string]interface{}{
"next": time.Now().Add(kit.Duration(arg[1])).Unix(),
"interval": arg[1], "cmd": arg[2:],
})
case "repeat":
// 周期命令
m.Rich(ice.GDB_TIMER, nil, kit.Dict(
"next", time.Now().Add(kit.Duration(arg[1])).Unix(),
"interval", arg[1], "cmd", arg[2:],
))
}
}},
ice.GDB_EVENT: {Name: "event", Help: "触发器", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
switch arg[0] {
case "listen":
m.Grow(ice.GDB_EVENT, arg[1], map[string]interface{}{"cmd": arg[2:]})
// 监听事件
m.Grow(ice.GDB_EVENT, arg[1], kit.Dict("cmd", arg[2:]))
m.Log(ice.LOG_LISTEN, "%s: %v", arg[1], arg[2:])
case "action":
// 触发事件
if f, ok := m.Target().Server().(*Frame); ok {
f.d <- arg[1:]
}

View File

@ -8,6 +8,11 @@ var Index = &ice.Context{Name: "lex", Help: "词法模块",
Caches: map[string]*ice.Cache{},
Configs: map[string]*ice.Config{},
Commands: map[string]*ice.Command{
ice.ICE_INIT: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
}},
ice.ICE_EXIT: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
}},
"hi": {Name: "hi", Help: "hello", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
m.Echo("hello %s world", c.Name)
}},

View File

@ -11,8 +11,8 @@ import (
type Log struct {
m *ice.Message
level string
str string
l string
s string
}
type Frame struct {
@ -23,9 +23,10 @@ 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.p = make(chan *Log, 100)
// 日志管道
f.p = make(chan *Log, 1024)
ice.Log = func(msg *ice.Message, level string, str string) {
f.p <- &Log{m: msg, level: level, str: str}
f.p <- &Log{m: msg, l: level, s: str}
}
return f
}
@ -34,13 +35,16 @@ func (f *Frame) Start(m *ice.Message, arg ...string) bool {
if l, ok := <-f.p; !ok {
break
} else {
file := kit.Select("bench", m.Conf("show", l.level+".file"))
// 日志文件
file := kit.Select("bench", m.Conf("show", l.l+".file"))
f := m.Confv("file", file+".file").(*os.File)
// 日志内容
ls := []string{l.m.Format("prefix"), " "}
ls = append(ls, m.Conf("show", l.level+".prefix"),
l.level, " ", l.str, m.Conf("show", l.level+".suffix"), "\n")
ls = append(ls, m.Conf("show", l.l+".prefix"),
l.l, " ", l.s, m.Conf("show", l.l+".suffix"), "\n")
// 输出日志
for _, v := range ls {
fmt.Fprintf(f, v)
}
@ -55,36 +59,54 @@ func (f *Frame) Close(m *ice.Message, arg ...string) bool {
var Index = &ice.Context{Name: "log", Help: "日志模块",
Caches: map[string]*ice.Cache{},
Configs: map[string]*ice.Config{
"file": &ice.Config{Name: "file", Value: map[string]interface{}{
"bench": map[string]interface{}{"path": "var/log/bench.log"},
}, Help: "信号"},
"show": &ice.Config{Name: "file", Value: map[string]interface{}{
"bench": map[string]interface{}{"file": "bench"},
"file": &ice.Config{Name: "file", Help: "日志文件", Value: kit.Dict(
"watch", kit.Dict("path", "var/log/watch.log"),
"bench", kit.Dict("path", "var/log/bench.log"),
"error", kit.Dict("path", "var/log/error.log"),
"trace", kit.Dict("path", "var/log/trace.log"),
)},
"show": &ice.Config{Name: "show", Help: "日志格式", Value: kit.Dict(
ice.LOG_ENABLE, kit.Dict("file", "watch"),
ice.LOG_IMPORT, kit.Dict("file", "watch"),
ice.LOG_CREATE, kit.Dict("file", "watch"),
ice.LOG_INSERT, kit.Dict("file", "watch"),
ice.LOG_EXPORT, kit.Dict("file", "watch"),
"cmd": map[string]interface{}{"file": "bench", "prefix": "\033[32m", "suffix": "\033[0m"},
"start": map[string]interface{}{"file": "bench", "prefix": "\033[32m", "suffix": "\033[0m"},
"serve": map[string]interface{}{"file": "bench", "prefix": "\033[32m", "suffix": "\033[0m"},
ice.LOG_LISTEN, kit.Dict("file", "bench"),
ice.LOG_SIGNAL, kit.Dict("file", "bench"),
ice.LOG_TIMERS, kit.Dict("file", "bench"),
ice.LOG_EVENTS, kit.Dict("file", "bench"),
"cost": map[string]interface{}{"file": "bench", "prefix": "\033[33m", "suffix": "\033[0m"},
ice.LOG_BEGIN, kit.Dict("file", "bench"),
ice.LOG_START, kit.Dict("file", "bench", "prefix", "\033[32m", "suffix", "\033[0m"),
ice.LOG_SERVE, kit.Dict("file", "bench", "prefix", "\033[32m", "suffix", "\033[0m"),
ice.LOG_CLOSE, kit.Dict("file", "bench", "prefix", "\033[31m", "suffix", "\033[0m"),
"warn": map[string]interface{}{"file": "bench", "prefix": "\033[31m", "suffix": "\033[0m"},
"close": map[string]interface{}{"file": "bench", "prefix": "\033[31m", "suffix": "\033[0m"},
}, Help: "信号"},
ice.LOG_CMDS, kit.Dict("file", "bench", "prefix", "\033[32m", "suffix", "\033[0m"),
ice.LOG_COST, kit.Dict("file", "bench", "prefix", "\033[33m", "suffix", "\033[0m"),
ice.LOG_INFO, kit.Dict("file", "bench"),
ice.LOG_WARN, kit.Dict("file", "bench", "prefix", "\033[31m", "suffix", "\033[0m"),
ice.LOG_ERROR, kit.Dict("file", "error"),
ice.LOG_TRACE, kit.Dict("file", "trace"),
)},
},
Commands: map[string]*ice.Command{
ice.ICE_INIT: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
m.Confm("file", nil, func(key string, value map[string]interface{}) {
// 日志文件
if f, p, e := kit.Create(kit.Format(value["path"])); m.Assert(e) {
m.Cap(ice.CTX_STREAM, path.Base(p))
m.Log("info", "log %s %s", key, p)
m.Log("create", "%s: %s", key, p)
value["file"] = f
}
})
}},
ice.ICE_EXIT: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
f := m.Target().Server().(*Frame)
if f, ok := m.Target().Server().(*Frame); ok {
// 关闭日志
ice.Log = nil
close(f.p)
}
}},
},
}

View File

@ -15,6 +15,11 @@ var Index = &ice.Context{Name: "mdb", Help: "数据模块",
Caches: map[string]*ice.Cache{},
Configs: map[string]*ice.Config{},
Commands: map[string]*ice.Command{
ice.ICE_INIT: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
}},
ice.ICE_EXIT: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
}},
"update": {Name: "update config table index key value", Help: "修改数据", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
meta := m.Confm(arg[0], arg[1]+".meta")
index := kit.Int(arg[2]) - kit.Int(meta["offset"]) - 1

View File

@ -131,6 +131,11 @@ var Index = &ice.Context{Name: "nfs", Help: "文件模块",
Caches: map[string]*ice.Cache{},
Configs: map[string]*ice.Config{},
Commands: map[string]*ice.Command{
ice.ICE_INIT: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
}},
ice.ICE_EXIT: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
}},
"dir": {Name: "dir", Help: "目录", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
rg, _ := regexp.Compile(m.Option("dir_reg"))
dir(m, arg[0], arg[1], 0, false, "both", rg,
@ -141,7 +146,7 @@ var Index = &ice.Context{Name: "nfs", Help: "文件模块",
defer f.Close()
for _, v := range arg[1:] {
if n, e := f.WriteString(v); m.Assert(e) {
m.Log("info", "save %v %v", n, p)
m.Log("export", "%v: %v", n, p)
m.Echo(p)
}
}

View File

@ -7,7 +7,9 @@ import (
_ "github.com/shylinux/icebergs/base/web"
_ "github.com/shylinux/icebergs/base/gdb"
_ "github.com/shylinux/icebergs/base/lex"
_ "github.com/shylinux/icebergs/base/log"
_ "github.com/shylinux/icebergs/base/yac"
_ "github.com/shylinux/icebergs/base/mdb"
_ "github.com/shylinux/icebergs/base/nfs"

View File

@ -14,6 +14,22 @@ import (
type Frame struct {
in io.ReadCloser
out io.WriteCloser
target *ice.Context
count int
}
func (f *Frame) prompt(m *ice.Message) *ice.Message {
prompt := "[15:04:05]%s> "
fmt.Fprintf(f.out, kit.Format("%d", f.count))
fmt.Fprintf(f.out, m.Time(prompt, f.target.Name))
return m
}
func (f *Frame) printf(m *ice.Message, res string) *ice.Message {
fmt.Fprint(f.out, res)
if !strings.HasSuffix(res, "\n") {
fmt.Fprint(f.out, "\n")
}
return m
}
func (f *Frame) Spawn(m *ice.Message, c *ice.Context, arg ...string) ice.Server {
@ -23,37 +39,52 @@ func (f *Frame) Begin(m *ice.Message, arg ...string) ice.Server {
return f
}
func (f *Frame) Start(m *ice.Message, arg ...string) bool {
switch kit.Select("stdio", arg, 0) {
default:
f.in = os.Stdin
f.out = os.Stdout
m.Cap(ice.CTX_STREAM, "stdio")
}
prompt := "%d[15:04:05]%s> "
target := m.Target()
count := 0
f.count = 0
f.target = m.Target()
bio := bufio.NewScanner(f.in)
fmt.Fprintf(f.out, m.Time(prompt, count, target.Name))
for bio.Scan() {
for f.prompt(m); bio.Scan(); f.prompt(m) {
ls := kit.Split(bio.Text())
m.Log("info", "stdin input %v", ls)
m.Log(ice.LOG_IMPORT, "stdin: %v", ls)
msg := m.Spawns(target)
if len(ls) > 0 && strings.HasPrefix(ls[0], "~") {
// 切换模块
target := ls[0][1:]
if ls = ls[1:]; len(target) == 0 {
target, ls = ls[0], ls[1:]
}
ice.Pulse.Search(target+".", func(p *ice.Context, s *ice.Context, key string) {
m.Info("choice: %s", s.Name)
f.target = s
})
}
if len(ls) == 0 {
continue
}
// 执行命令
msg := m.Spawns(f.target)
if msg.Cmdy(ls); !msg.Hand {
msg = msg.Set("result").Cmdy(ice.CLI_SYSTEM, ls)
}
// 生成结果
res := msg.Result()
if res == "" {
msg.Table()
res = msg.Result()
res = msg.Table().Result()
}
fmt.Fprint(f.out, res)
if !strings.HasSuffix(res, "\n") {
fmt.Fprint(f.out, "\n")
}
fmt.Fprintf(f.out, m.Time(prompt, count, target.Name))
msg.Cost("stdin %v", ls)
count++
// 输出结果
msg.Cost("stdin:%v", ls)
f.printf(msg, res)
f.count++
}
return true
}
@ -66,12 +97,13 @@ var Index = &ice.Context{Name: "ssh", Help: "终端模块",
Configs: map[string]*ice.Config{},
Commands: map[string]*ice.Command{
ice.ICE_INIT: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
m.Echo("hello %s world", c.Name)
}},
ice.ICE_EXIT: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
f := m.Target().Server().(*Frame)
if f, ok := m.Target().Server().(*Frame); ok {
// 关闭终端
f.in.Close()
m.Done()
}
}},
},
}

View File

@ -11,6 +11,11 @@ var Index = &ice.Context{Name: "tcp", Help: "网络模块",
Caches: map[string]*ice.Cache{},
Configs: map[string]*ice.Config{},
Commands: map[string]*ice.Command{
ice.ICE_INIT: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
}},
ice.ICE_EXIT: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
}},
"ifconfig": {Name: "ifconfig [name]", Help: "网络配置", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
if ifs, e := net.Interfaces(); m.Assert(e) {
for _, v := range ifs {

View File

@ -68,8 +68,8 @@ func (web *Frame) Login(msg *ice.Message, w http.ResponseWriter, r *http.Request
}
return msg.Option(ice.MSG_USERURL) != ""
}
func (web *Frame) HandleWSS(m *ice.Message, safe bool, c *websocket.Conn) bool {
for {
func (web *Frame) HandleWSS(m *ice.Message, safe bool, c *websocket.Conn, name string) bool {
for running := true; running; {
if t, b, e := c.ReadMessage(); m.Warn(e != nil, "space recv %d msg %v", t, e) {
break
} else {
@ -77,38 +77,40 @@ func (web *Frame) HandleWSS(m *ice.Message, safe bool, c *websocket.Conn) bool {
case MSG_MAPS:
// 接收报文
socket, msg := c, m.Spawn(b)
source := kit.Simple(msg.Optionv(ice.MSG_SOURCE))
source := kit.Simple(msg.Optionv(ice.MSG_SOURCE), name)
target := kit.Simple(msg.Optionv(ice.MSG_TARGET))
msg.Info("recv %v %v->%v %v", t, source, target, msg.Format("meta"))
if len(target) == 0 {
// 本地执行
if msg.Optionv(ice.MSG_HANDLE, "true"); !msg.Warn(!safe, "no right") {
m.Option("_dev", name)
msg = msg.Cmd()
}
kit.Revert(source)
source, target = []string{source[0]}, source[1:]
if source, target = []string{}, kit.Revert(source)[1:]; msg.Detail() == "exit" {
return true
}
} else if s, ok := msg.Confv(ice.WEB_SPACE, kit.Keys("hash", target[0], "socket")).(*websocket.Conn); ok {
// 转发报文
socket, source, target = s, source, target[1:]
msg.Info("space route")
socket, source, target = s, append(source, target[0]), target[1:]
} else if call, ok := web.send[msg.Option(ice.MSG_TARGET)]; len(target) == 1 && ok {
// 接收响应
msg.Info("space done")
delete(web.send, msg.Option(ice.MSG_TARGET))
msg.Info("space done")
call.Back(msg)
break
} else if msg.Warn(msg.Option("_handle") == "true", "space miss") {
// 丢弃报文
// 回复失败
break
} else {
// 失败报文
// 下发失败
msg.Warn(true, "space error")
source, target = []string{source[len(source)-1]}, kit.Revert(source)[1:]
source, target = []string{}, kit.Revert(source)[1:]
}
// 发送报文
@ -117,9 +119,6 @@ func (web *Frame) HandleWSS(m *ice.Message, safe bool, c *websocket.Conn) bool {
socket.WriteMessage(t, []byte(msg.Format("meta")))
msg.Info("send %v %v->%v %v", t, source, target, msg.Format("meta"))
msg.Log("cost", "%s: ", msg.Format("cost"))
if msg.Detail() == "exit" {
return true
}
}
}
}
@ -335,7 +334,11 @@ var Index = &ice.Context{Name: "web", Help: "网页模块",
ice.WEB_SERVE: {Name: "serve", Help: "服务器", Value: kit.Data(
"static", map[string]interface{}{"/": "usr/volcanos/",
"/static/volcanos/": "usr/volcanos/",
"/publish/": "usr/publish/",
},
"volcanos", kit.Dict("path", "usr/volcanos",
"repos", "https://github.com/shylinux/volcanos",
"branch", "master"),
"template", map[string]interface{}{"path": "usr/template", "list": []interface{}{
`{{define "raw"}}{{.Result}}{{end}}`,
}},
@ -360,18 +363,19 @@ var Index = &ice.Context{Name: "web", Help: "网页模块",
Commands: map[string]*ice.Command{
ice.ICE_INIT: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
m.Cmd(ice.CTX_CONFIG, "load", "web.json")
if m.Richs(ice.WEB_SPIDE, nil, "self", nil) == nil {
m.Cmd(ice.WEB_SPIDE, "add", "self", "http://:9020")
m.Cmd(ice.WEB_SPIDE, "add", "self", kit.Select("http://:9020", os.Getenv("ctx_dev")))
m.Cmd(ice.WEB_SPIDE, "add", "self", kit.Select("http://:9020", m.Conf(ice.CLI_RUNTIME, "conf.ctx_self")))
}
if m.Richs(ice.WEB_SPIDE, nil, "dev", nil) == nil {
m.Cmd(ice.WEB_SPIDE, "add", "dev", kit.Select("http://:9020", os.Getenv("ctx_dev")))
m.Cmd(ice.WEB_SPIDE, "add", "dev", kit.Select("http://mac.local:9020", m.Conf(ice.CLI_RUNTIME, "conf.ctx_dev")))
}
if m.Richs(ice.WEB_SPIDE, nil, "shy", nil) == nil {
m.Cmd(ice.WEB_SPIDE, "add", "shy", "https://shylinux.com")
m.Cmd(ice.WEB_SPIDE, "add", "shy", kit.Select("https://shylinux.com:443", m.Conf(ice.CLI_RUNTIME, "conf.ctx_shy")))
}
}},
ice.ICE_EXIT: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
m.Done()
m.Done()
m.Cmd(ice.CTX_CONFIG, "save", "web.json", ice.WEB_SPIDE, ice.WEB_FAVOR, ice.WEB_CACHE, ice.WEB_STORY, ice.WEB_SHARE)
}},
@ -418,6 +422,7 @@ var Index = &ice.Context{Name: "web", Help: "网页模块",
"url", arg[2],
),
))
m.Log(ice.LOG_CREATE, "%s: %v", arg[1], arg[2:])
}
default:
// spide shy [cache] [POST|GET] uri file|data|form|part|json arg...
@ -562,21 +567,15 @@ var Index = &ice.Context{Name: "web", Help: "网页模块",
}
}},
ice.WEB_SERVE: {Name: "serve", Help: "服务器", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
// 节点信息
m.Conf(ice.CLI_RUNTIME, "node.name", m.Conf(ice.CLI_RUNTIME, "boot.hostname"))
m.Conf(ice.CLI_RUNTIME, "node.type", kit.MIME_SERVER)
m.Conf(ice.CLI_RUNTIME, "node.type", ice.WEB_SERVER)
m.Rich(ice.WEB_SPACE, nil, kit.Dict(
"type", kit.MIME_MYSELF,
"name", m.Conf(ice.CLI_RUNTIME, "boot.hostname"),
"user", m.Conf(ice.CLI_RUNTIME, "boot.username"),
))
if _, e := os.Stat("usr/volcanos"); e != nil {
m.Cmd("cli.system", "git", "clone", "https://github.com/shylinux/volcanos", "usr/volcanos")
}
if m.Conf(ice.CLI_RUNTIME, "boot.count") == "1" {
m.Event(ice.SYSTEM_INIT)
}
// 启动服务
m.Target().Start(m, kit.Select("self", arg, 0))
m.Richs(ice.WEB_SPIDE, nil, "dev", func(key string, value map[string]interface{}) {
m.Cmd(ice.WEB_SPACE, "connect", "dev")
})
}},
ice.WEB_SPACE: {Name: "space", Help: "空间站", Meta: kit.Dict("exports", []string{"pod", "name"}), List: kit.List(
kit.MDB_INPUT, "text", "name", "pod",
@ -591,13 +590,6 @@ var Index = &ice.Context{Name: "web", Help: "网页模块",
m.Sort("name")
return
}
if len(arg) == 1 {
// 节点详情
m.Richs(ice.WEB_SPACE, nil, arg[0], func(key string, value map[string]interface{}) {
m.Push("detail", value)
})
return
}
web := m.Target().Server().(*Frame)
switch arg[0] {
@ -606,9 +598,9 @@ var Index = &ice.Context{Name: "web", Help: "网页模块",
case "add":
m.Cmdy(ice.WEB_SPIDE, "self", path.Join("/space/share/add", path.Join(arg[2:]...)))
default:
m.Richs(ice.WEB_SPIDE, nil, "self", func(key string, value map[string]interface{}) {
m.Richs(ice.WEB_SPIDE, nil, m.Option("_dev"), func(key string, value map[string]interface{}) {
m.Log(ice.LOG_CREATE, "dev: %s share: %s", m.Option("_dev"), arg[1])
value["share"] = arg[1]
m.Info("what %v", kit.Formats(value))
})
}
@ -626,20 +618,25 @@ var Index = &ice.Context{Name: "web", Help: "网页模块",
case "connect":
// 基本信息
dev := kit.Select("dev", arg, 1)
node := m.Conf(ice.CLI_RUNTIME, "node.type")
name := kit.Select(m.Conf(ice.CLI_RUNTIME, "boot.pathname"), m.Conf(ice.CLI_RUNTIME, "boot.hostname"), node == kit.MIME_SERVER)
name := m.Conf(ice.CLI_RUNTIME, "node.name")
user := m.Conf(ice.CLI_RUNTIME, "boot.username")
m.Richs(ice.WEB_SPIDE, nil, kit.Select("self", arg, 1), func(key string, value map[string]interface{}) {
m.Hold(1).Gos(m, func(m *ice.Message) {
m.Richs(ice.WEB_SPIDE, nil, dev, func(key string, value map[string]interface{}) {
proto := kit.Select("ws", "wss", kit.Format(kit.Value(value, "client.protocol")) == "https")
host := kit.Format(kit.Value(value, "client.hostname"))
for i := 0; i < m.Confi(ice.WEB_SPACE, "meta.redial.c"); i++ {
if u, e := url.Parse(kit.MergeURL("ws://"+host+"/space/", "node", node, "name", name, "user", user, "share", value["share"])); m.Assert(e) {
if u, e := url.Parse(kit.MergeURL(proto+"://"+host+"/space/", "node", node, "name", name, "user", user, "share", value["share"])); m.Assert(e) {
if s, e := net.Dial("tcp", host); !m.Warn(e != nil, "%s", e) {
if s, _, e := websocket.NewClient(s, u, nil, m.Confi(ice.WEB_SPACE, "meta.buffer.r"), m.Confi(ice.WEB_SPACE, "meta.buffer.w")); !m.Warn(e != nil, "%s", e) {
// 连接成功
m.Info("conn %d success %s", i, u)
if i = 0; web.HandleWSS(m, true, s) {
m.Rich(ice.WEB_SPACE, nil, kit.Dict(kit.MDB_TYPE, ice.WEB_MASTER, kit.MDB_NAME, dev))
m.Info("%d conn %s success %s", i, dev, u)
if i = 0; web.HandleWSS(m, true, s, dev) {
break
}
}
@ -652,10 +649,20 @@ var Index = &ice.Context{Name: "web", Help: "网页模块",
}
}
})
m.Done()
})
default:
if len(arg) == 1 {
// 节点详情
m.Richs(ice.WEB_SPACE, nil, arg[0], func(key string, value map[string]interface{}) {
m.Push("detail", value)
})
break
}
if arg[0] == "" {
// 本地命令
if arg[0] == "" || arg[0] == m.Conf(ice.CLI_RUNTIME, "node.name") {
m.Cmdy(arg[1:])
break
}
@ -665,11 +672,11 @@ var Index = &ice.Context{Name: "web", Help: "网页模块",
if socket, ok := value["socket"].(*websocket.Conn); ok {
// 构造路由
id := kit.Format(c.ID())
m.Optionv(ice.MSG_SOURCE, []string{id, target[0]})
m.Optionv(ice.MSG_SOURCE, []string{id})
m.Optionv(ice.MSG_TARGET, target[1:])
m.Set(ice.MSG_DETAIL, arg[1:]...)
m.Option("hot", m.Option("hot"))
m.Option("top", m.Option("top"))
m.Set(ice.MSG_DETAIL, arg[1:]...)
m.Info("send %s %s", id, m.Format("meta"))
// 下发命令
@ -846,7 +853,7 @@ var Index = &ice.Context{Name: "web", Help: "网页模块",
kit.MDB_TYPE, arg[1], kit.MDB_NAME, arg[2], kit.MDB_TEXT, arg[3],
"extra", extra,
))
m.Info("create favor: %s index: %d name: %s", favor, index, arg[2])
m.Log(ice.LOG_INSERT, "favor: %s index: %d name: %s", favor, index, arg[2])
m.Echo("%d", index)
}},
ice.WEB_CACHE: {Name: "cache", Help: "缓存池", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
@ -861,6 +868,22 @@ var Index = &ice.Context{Name: "web", Help: "网页模块",
}
switch arg[0] {
case "catch":
if f, e := os.Open(arg[2]); m.Assert(e) {
defer f.Close()
h := kit.Hashs(f)
if o, p, e := kit.Create(path.Join(m.Conf(ice.WEB_CACHE, ice.Meta("path")), h[:2], h)); m.Assert(e) {
defer o.Close()
f.Seek(0, os.SEEK_SET)
if n, e := io.Copy(o, f); m.Assert(e) {
m.Log(ice.LOG_IMPORT, "%s: %s", kit.FmtSize(n), p)
arg = kit.Simple(arg[0], arg[1], path.Base(arg[2]), p, p, n)
}
}
}
fallthrough
case "upload", "download":
// 打开文件
if m.R != nil {
@ -901,7 +924,7 @@ var Index = &ice.Context{Name: "web", Help: "网页模块",
kit.MDB_FILE, kit.Select("", arg, 4), kit.MDB_SIZE, size,
)
h := m.Rich(ice.WEB_CACHE, nil, data)
m.Info("cache: %s type: %s name: %s", h, arg[1], arg[2])
m.Log(ice.LOG_CREATE, "cache: %s %s: %s", h, arg[1], arg[2])
// 保存数据
if arg[0] == "add" && len(arg) == 4 {
@ -960,9 +983,11 @@ var Index = &ice.Context{Name: "web", Help: "网页模块",
// head list data time text file
switch arg[0] {
case "catch":
fallthrough
case "add", "upload":
// 保存数据
if m.Richs(ice.WEB_CACHE, nil, arg[3], nil) == nil {
if m.Richs(ice.WEB_CACHE, nil, kit.Select("", arg, 3), nil) == nil {
m.Cmdy(ice.WEB_CACHE, arg)
arg = []string{arg[0], m.Append("type"), m.Append("name"), m.Append("data")}
}
@ -978,7 +1003,7 @@ var Index = &ice.Context{Name: "web", Help: "网页模块",
list := m.Rich(ice.WEB_STORY, nil, kit.Dict(
"count", count+1, "scene", arg[1], "story", arg[2], "data", arg[3], "prev", prev,
))
m.Info("%s: %s story: %s", arg[1], arg[2], list)
m.Log(ice.LOG_CREATE, "story: %s %s: %s", list, arg[1], arg[2])
m.Push("list", list)
// 添加索引
@ -1136,7 +1161,7 @@ var Index = &ice.Context{Name: "web", Help: "网页模块",
kit.MDB_TYPE, arg[1], kit.MDB_NAME, arg[2], kit.MDB_TEXT, arg[3],
"share", h,
))
m.Info("share: %s %s", h, extra)
m.Log(ice.LOG_CREATE, "share: %s extra: %s", h, kit.Format(extra))
m.Echo(h)
}
}},
@ -1188,7 +1213,7 @@ var Index = &ice.Context{Name: "web", Help: "网页模块",
return
}
if s, e := websocket.Upgrade(m.W, m.R, nil, m.Confi(ice.WEB_SPACE, "meta.buffer"), m.Confi(ice.WEB_SPACE, "meta.buffer")); m.Assert(e) {
if s, e := websocket.Upgrade(m.W, m.R, nil, m.Confi(ice.WEB_SPACE, "meta.buffer.r"), m.Confi(ice.WEB_SPACE, "meta.buffer.w")); m.Assert(e) {
// 共享空间
share := m.Option("share")
if m.Richs(ice.WEB_SHARE, nil, share, nil) == nil {
@ -1200,17 +1225,16 @@ var Index = &ice.Context{Name: "web", Help: "网页模块",
kit.MDB_TYPE, m.Option("node"),
kit.MDB_NAME, m.Option("name"),
kit.MDB_USER, m.Option("user"),
"share", share,
"socket", s,
"share", share, "socket", s,
))
m.Info("space: %s", m.Option(kit.MDB_NAME))
m.Log(ice.LOG_CREATE, "space: %s share: %s", m.Option(kit.MDB_NAME), share)
m.Gos(m, func(m *ice.Message) {
// 监听消息
m.Event(ice.SPACE_START, m.Option("node"), m.Option("name"))
m.Target().Server().(*Frame).HandleWSS(m, false, s)
m.Target().Server().(*Frame).HandleWSS(m, false, s, m.Option("name"))
m.Log(ice.LOG_CLOSE, "%s: %s", m.Option(kit.MDB_NAME), kit.Format(m.Confv(ice.WEB_SPACE, kit.Keys(kit.MDB_HASH, h))))
m.Event(ice.SPACE_CLOSE, m.Option("node"), m.Option("name"))
m.Log("close", "%s: %s", m.Option(kit.MDB_NAME), kit.Format(m.Confv(ice.WEB_SPACE, kit.Keys(kit.MDB_HASH, h))))
m.Confv(ice.WEB_SPACE, kit.Keys(kit.MDB_HASH, h), "")
})

View File

@ -8,6 +8,11 @@ var Index = &ice.Context{Name: "yac", Help: "语法模块",
Caches: map[string]*ice.Cache{},
Configs: map[string]*ice.Config{},
Commands: map[string]*ice.Command{
ice.ICE_INIT: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
}},
ice.ICE_EXIT: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
}},
"hi": {Name: "hi", Help: "hello", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
m.Echo("hello %s world", c.Name)
}},

View File

@ -1,7 +1,5 @@
#! /bin/sh
ice_sh=${ice_sh:="ice.sh"}
prepare() {
[ -f main.go ] || cat >> main.go <<END
package main
@ -20,41 +18,56 @@ END
[ -f go.mod ] || go mod init ${PWD##**/}
[ -f ${ice_sh} ] || cat >> ${ice_sh} <<END
[ -f Makefile ] || cat >> Makefile <<END
all:
go build -o ice.bin main.go && chmod u+x ice.bin && ./ice.sh restart
END
[ -f ice.sh ] || cat >> ice.sh <<END
#! /bin/sh
export PATH=\${PWD}/bin:\${PWD}:\$PATH
export PATH=\${PWD}:\$PATH
export ctx_pid=var/run/ice.pid
prepare() {
which ice.bin && return
curl -s https://shylinux.com/publish/ice.bin -o bin/ice.bin
[ -e ice.sh ] || curl \$ctx_dev/publish/ice.sh -o ice.sh && chmod u+x ice.sh
[ -e ice.bin ] && chmod u+x ice.bin && return
bin="ice"
case \`uname -s\` in
Darwin) bin=\${bin}.darwin ;;
Linux) bin=\${bin}.linux ;;
*) bin=\${bin}.windows ;;
esac
case \`uname -m\` in
x86_64) bin=\${bin}.amd64 ;;
i686) bin=\${bin}.386 ;;
arm*) bin=\${bin}.arm ;;
esac
curl \$ctx_dev/publish/\${bin} -o ice.bin && chmod u+x ice.bin
}
start() {
prepare && while true; do
prepare && shutdown && while true; do
date && ice.bin \$@ 2>boot.log && echo -e "\n\nrestarting..." || break
done
}
restart() {
kill -2 \`cat var/run/shy.pid\`
[ -e \$ctx_pid ] && kill -2 \`cat \$ctx_pid\` || echo
}
shutdown() {
kill -3 \`cat var/run/shy.pid\`
[ -e \$ctx_pid ] && kill -3 \`cat \$ctx_pid\` || echo
}
cmd=\$1 && shift
[ -z "\$cmd" ] && cmd=start
cmd=\$1 && [ -n "\$cmd" ] && shift || cmd=start
\$cmd \$*
END
chmod u+x ${ice_sh}
[ -f Makefile ] || cat >> Makefile <<END
all:
go build -o bin/ice.bin main.go && chmod u+x bin/ice.bin && ./${ice_sh} restart
END
chmod u+x ice.sh
}
build() {
[ "$1" != "" ] && mkdir $1 && cd $1
prepare && go build -o bin/ice.bin main.go && chmod u+x bin/ice.bin && ./${ice_sh}
miss=./ && [ "$1" != "" ] && miss=$1 && shift && mkdir $miss
cd $miss && prepare && go build -o ice.bin main.go && chmod u+x ice.bin && ./ice.sh start
}
build $*
cmd=build && [ "$1" != "" ] && cmd=$1 && shift
$cmd $*

32
conf.go
View File

@ -62,27 +62,41 @@ const ( // WEB
WEB_PROXY = "proxy"
WEB_GROUP = "group"
WEB_LABEL = "label"
WEB_MASTER = "master"
WEB_MYSELF = "myself"
WEB_SERVER = "server"
WEB_WORKER = "worker"
)
const ( // LOG
LOG_ENABLE = "enable"
LOG_IMPORT = "import"
LOG_CREATE = "create"
LOG_INSERT = "insert"
LOG_EXPORT = "export"
LOG_LISTEN = "listen"
LOG_SIGNAL = "signal"
LOG_TIMERS = "timers"
LOG_EVENTS = "events"
LOG_BEGIN = "begin"
LOG_START = "start"
LOG_SERVE = "serve"
LOG_CLOSE = "close"
LOG_CMDS = "cmds"
LOG_COST = "cost"
LOG_INFO = "info"
LOG_WARN = "warn"
LOG_ERROR = "error"
LOG_TRACE = "trace"
LOG_BEGIN = "begin"
LOG_START = "start"
LOG_BENCH = "bench"
LOG_CLOSE = "close"
)
const ( // GDB
GDB_SIGNAL = "signal"
GDB_TIMER = "timer"
GDB_EVENT = "event"
SYSTEM_INIT = "system.init"
SERVE_START = "serve.start"
SERVE_CLOSE = "serve.close"
SPACE_START = "space.start"
@ -181,4 +195,8 @@ var Alias = map[string]string{
APP_NOTE: "web.wiki.note",
APP_MISS: "web.team.miss",
"compile": "web.code.compile",
"publish": "web.code.publish",
"upgrade": "web.code.upgrade",
}

View File

@ -118,7 +118,7 @@ var Index = &ice.Context{Name: "chat", Help: "聊天模块",
"user", kit.Data(kit.MDB_SHORT, "username"),
"tool", kit.Data(),
))
m.Info("create river: %v name: %v", river, arg[1])
m.Log("create", "river: %v name: %v", river, arg[1])
m.Cmd("/river", river, "add", arg[2:])
m.Echo(river)
}
@ -144,7 +144,7 @@ var Index = &ice.Context{Name: "chat", Help: "聊天模块",
// 添加用户
for _, v := range arg[2:] {
user := m.Rich(ice.CHAT_RIVER, kit.Keys(kit.MDB_HASH, arg[0], "user"), kit.Data("username", v))
m.Info("add river: %s user: %s name: %s", arg[0], user, v)
m.Log("insert", "river: %s user: %s name: %s", arg[0], user, v)
}
}
}
@ -170,7 +170,7 @@ var Index = &ice.Context{Name: "chat", Help: "聊天模块",
id := m.Grow(ice.CHAT_RIVER, kit.Keys(prefix, kit.MDB_HASH, arg[1]), kit.Data(
"pod", arg[i], "ctx", arg[i+1], "cmd", arg[i+2], "key", arg[i+3],
))
m.Info("create tool %d %v", id, arg[i:i+4])
m.Log("insert", "storm: %s %d: %v", arg[1], id, arg[i:i+4])
}
case "rename":
// 重命名应用
@ -181,7 +181,7 @@ var Index = &ice.Context{Name: "chat", Help: "聊天模块",
case "remove":
// 删除应用
m.Richs(ice.CHAT_RIVER, kit.Keys(prefix), arg[1], func(value map[string]interface{}) {
m.Info("remove storm: %s %s", arg[1], kit.Format(value))
m.Log("remove", "storm: %s value: %s", arg[1], kit.Format(value))
})
m.Conf(ice.CHAT_RIVER, kit.Keys(prefix, kit.MDB_HASH, arg[1]), "")
}
@ -201,7 +201,7 @@ var Index = &ice.Context{Name: "chat", Help: "聊天模块",
storm := m.Rich(ice.CHAT_RIVER, kit.Keys(kit.MDB_HASH, arg[0], "tool"), kit.Dict(
kit.MDB_META, kit.Dict(kit.MDB_NAME, arg[2]),
))
m.Info("create river: %s storm: %s name: %v", arg[0], storm, arg[2])
m.Log("create", "storm: %s name: %v", storm, arg[2])
m.Cmd("/storm", arg[0], storm, "add", arg[3:])
m.Echo(storm)

View File

@ -30,6 +30,10 @@ var Index = &ice.Context{Name: "code", Help: "编程模块",
Caches: map[string]*ice.Cache{},
Configs: map[string]*ice.Config{
"login": {Name: "login", Help: "登录", Value: kit.Data()},
"compile": {Name: "compile", Help: "编译", Value: kit.Data("path", "usr/publish")},
"publish": {Name: "publish", Help: "发布", Value: kit.Data("path", "usr/publish")},
"upgrade": {Name: "upgrade", Help: "升级", Value: kit.Data("path", "usr/publish")},
},
Commands: map[string]*ice.Command{
ice.ICE_INIT: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
@ -39,6 +43,63 @@ var Index = &ice.Context{Name: "code", Help: "编程模块",
m.Cmd(ice.CTX_CONFIG, "save", "code.json", "web.code.login")
}},
"compile": {Name: "compile", Help: "编译", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
if len(arg) == 0 {
// 目录列表
m.Cmdy("nfs.dir", "", m.Conf("publish", "meta.path"))
return
}
// 编译目标
main := kit.Select("main.go", arg, 2)
arch := kit.Select(m.Conf(ice.CLI_RUNTIME, "host.GOARCH"), arg, 1)
goos := kit.Select(m.Conf(ice.CLI_RUNTIME, "host.GOOS"), arg, 0)
file := path.Join(m.Conf("compile", "meta.path"), kit.Keys("ice", goos, arch))
// 编译参数
m.Add("option", "cmd_env", "GOCACHE", os.Getenv("GOCACHE"))
m.Add("option", "cmd_env", "GOARCH", arch, "GOOS", goos)
m.Add("option", "cmd_env", "HOME", os.Getenv("HOME"))
m.Cmd("cli.system", "go", "build", "-o", file, main)
// 编译记录
m.Cmdy(ice.WEB_STORY, "catch", "bin", file)
m.Log(ice.LOG_EXPORT, "%s: %s", main, file)
}},
"publish": {Name: "publish", Help: "发布", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
if len(arg) == 0 {
// 目录列表
m.Cmdy("nfs.dir", "", m.Conf("publish", "meta.path"))
return
}
p := arg[0]
if s, e := os.Stat(arg[0]); m.Assert(e) && s.IsDir() {
// 发布目录
p = path.Base(arg[0]) + ".tar.gz"
m.Cmd("cli.system", "tar", "-zcf", p, arg[0])
defer func() { os.Remove(p) }()
arg[0] = p
}
// 发布文件
target := path.Join(m.Conf("publish", "meta.path"), path.Base(arg[0]))
os.Remove(target)
os.Link(arg[0], target)
// 发布记录
m.Cmdy(ice.WEB_STORY, "catch", "bin", p)
m.Log(ice.LOG_EXPORT, "%s: %s", arg[0], target)
}},
"upgrade": {Name: "upgrade", Help: "升级", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
os.Rename("ice.sh", "ice.sh.bak")
os.Link(m.Cmd(ice.WEB_STORY, "index", m.Cmdx(ice.WEB_SPIDE, "dev", "cache", "/publish/ice.sh")).Append("file"), "ice.sh")
os.Rename("ice.bin", "ice.bin.bak")
os.Link(m.Cmd(ice.WEB_STORY, "index", m.Cmdx(ice.WEB_SPIDE, "dev", "cache", kit.Keys("/publish/ice",
m.Conf(ice.CLI_RUNTIME, "host.GOOS"), m.Conf(ice.CLI_RUNTIME, "host.GOARCH")))).Append("file"), "ice.bin")
}},
"login": {Name: "login", Help: "登录", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
switch kit.Select("list", arg, 0) {
case "open":

2
go.sum
View File

@ -4,4 +4,6 @@ github.com/gorilla/websocket v1.4.1 h1:q7AeDBpnBk8AogcD4DSag/Ukw/KV+YhzLj2bP5HvK
github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/shylinux/toolkits v0.0.0-20191225132906-3c11db083b5b h1:BXDEMcpHmwuwoqY/NWehDs11GOy2x+2MS7Xfihb3zFY=
github.com/shylinux/toolkits v0.0.0-20191225132906-3c11db083b5b/go.mod h1:Y68Ot6xOmo1bun67YvqC3chDGeU2gDxtsUnvVDGJm4g=
github.com/shylinux/toolkits v0.1.0 h1:7ghnVEjuwLf7zBsyeR37ahm2gaOKIyjSw9F9Pp9oTBU=
github.com/shylinux/toolkits v0.1.0/go.mod h1:Y68Ot6xOmo1bun67YvqC3chDGeU2gDxtsUnvVDGJm4g=
golang.org/dl v0.0.0-20190829154251-82a15e2f2ead/go.mod h1:IUMfjQLJQd4UTqG1Z90tenwKoCX93Gn3MAQJMOSBsDQ=

View File

@ -12,13 +12,27 @@ import (
var Index = &ice.Context{Name: "git", Help: "代码管理",
Caches: map[string]*ice.Cache{},
Configs: map[string]*ice.Config{
"buffer": {Name: "buffer", Help: "缓存", Value: kit.Data()},
"repos": {Name: "repos", Help: "仓库", Value: kit.Data(kit.MDB_SHORT, "name")},
},
Commands: map[string]*ice.Command{
ice.ICE_INIT: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
// 前端代码
m.Rich("repos", nil, kit.Data(
"name", "volcanos", "path", "usr/volcanos", "branch", "master",
"remote", "https://github.com/shylinux/volcanos",
))
m.Watch(ice.SERVE_START, "cli.git.check", "volcanos")
}},
ice.ICE_EXIT: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
}},
"check": {Name: "check", Help: "检查", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
m.Richs("repos", nil, arg[0], func(key string, value map[string]interface{}) {
if _, e := os.Stat(kit.Format(kit.Value(value, "meta.path"))); e != nil && os.IsNotExist(e) {
m.Cmd("cli.system", "git", "clone", kit.Value(value, "meta.remote"),
"-b", kit.Value(value, "meta.branch"), kit.Value(value, "meta.path"))
}
})
}},
"sum": {Name: "sum", Help: "统计", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
total := false
if len(arg) > 0 && arg[0] == "total" {

View File

@ -53,6 +53,8 @@ var Index = &ice.Context{Name: "tmux", Help: "终端模块",
Commands: map[string]*ice.Command{
ice.ICE_INIT: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
m.Watch(ice.DREAM_START, "cli.tmux.auto")
return
m.Watch(ice.SERVE_START, "cli.tmux.auto")
for _, p := range []string{"auto.sh", "auto.vim"} {
if m.Richs(ice.WEB_STORY, "head", p, nil) == nil {
m.Cmd(ice.WEB_STORY, "add", ice.TYPE_SHELL, p, m.Cmdx(ice.WEB_SPIDE, "shy", "cache", "GET", "/publish/"+p))

59
miss/miss.md Normal file
View File

@ -0,0 +1,59 @@
# icebergs
icebergs是一个后端框架通过模块化、集群化实现资源的无限的扩展与自由的组合。
一键创建项目
```
mkdir miss; cd miss && curl -s https://shylinux.com/publish/build.sh | sh
```
## 命令模块 base/cli
cli模块用于与系统进行交互。
- 系统信息 ice.CLI_RUNTIME
- 系统命令 ice.CLI_SYSTEM
## 终端模块 base/ssh
ssh模块用于与终端交互。
## 日志模块 base/log
log模块负责输出日志。
## 事件模块 base/gdb
gdb模块会根据各种触发条件择机执行各种命令。
- 信号器 ice.SIGNAL
- 定时器 ice.TIMER
- 触发器 ice.EVENT
## 认证模块 base/aaa
aaa模块用于各种权限管理与身份认证。
- 角色 ice.AAA_ROLE
- 用户 ice.AAA_USER
- 会话 ice.AAA_SESS
## 网页模块 base/web
web模块用于组织网络节点与生成前端网页
- 网络爬虫 ice.WEB_SPIDE
- 网络服务 ice.WEB_SERVE
- 网络节点 ice.WEB_SPACE
- 网络任务 ice.WEB_DREAM
- 网络收藏 ice.WEB_FAVOR
- 网络缓存 ice.WEB_CACHE
- 网络存储 ice.WEB_STORY
- 网络共享 ice.WEB_SHARE
- 网络路由 ice.WEB_ROUTE
- 网络代理 ice.WEB_PROXY
- 网络分组 ice.WEB_GROUP
- 网络标签 ice.WEB_LABEL

44
type.go
View File

@ -114,11 +114,7 @@ func (c *Context) Begin(m *Message, arg ...string) *Context {
}
func (c *Context) Start(m *Message, arg ...string) bool {
c.start = m
if c.context != nil && c.context.wg != nil {
c.context.wg.Add(1)
} else {
c.root.wg.Add(1)
}
m.Hold(1)
wait := make(chan bool)
m.Gos(m, func(m *Message) {
@ -606,19 +602,27 @@ func (m *Message) Result(arg ...interface{}) string {
}
func (m *Message) Log(level string, str string, arg ...interface{}) *Message {
str = strings.TrimSpace(fmt.Sprintf(str, arg...))
if Log != nil {
if str = strings.TrimSpace(fmt.Sprintf(str, arg...)); Log != nil {
Log(m, level, str)
}
prefix, suffix := "", ""
switch level {
case LOG_CMDS, "start", "serve":
case LOG_ENABLE, LOG_IMPORT, LOG_CREATE, LOG_INSERT, LOG_EXPORT:
prefix, suffix = "\033[36;44m", "\033[0m"
case LOG_LISTEN, LOG_SIGNAL, LOG_TIMERS, LOG_EVENTS:
prefix, suffix = "\033[33m", "\033[0m"
case LOG_CMDS, LOG_START, LOG_SERVE:
prefix, suffix = "\033[32m", "\033[0m"
case LOG_COST:
prefix, suffix = "\033[33m", "\033[0m"
case LOG_WARN, LOG_ERROR, "close":
case LOG_WARN, LOG_ERROR, LOG_CLOSE:
prefix, suffix = "\033[31m", "\033[0m"
}
// 输出日志
fmt.Fprintf(os.Stderr, "%s %02d %9s %s%s %s%s\n",
m.time.Format(ICE_TIME), m.code, fmt.Sprintf("%s->%s", m.source.Name, m.target.Name),
prefix, level, str, suffix)
@ -691,11 +695,11 @@ func (m *Message) TryCatch(msg *Message, safe bool, hand ...func(msg *Message))
case io.EOF:
case nil:
default:
m.Log(LOG_ERROR, "catch: %s", e)
m.Log(LOG_BENCH, "chain: %s", msg.Format("chain"))
m.Log(LOG_ERROR, "catch: %s", e)
m.Log(LOG_BENCH, "stack: %s", msg.Format("stack"))
if m.Log(LOG_ERROR, "catch: %s", e); len(hand) > 1 {
m.Log(LOG_WARN, "catch: %s", e)
m.Log(LOG_INFO, "chain: %s", msg.Format("chain"))
m.Log(LOG_WARN, "catch: %s", e)
m.Log(LOG_INFO, "stack: %s", msg.Format("stack"))
if m.Log(LOG_WARN, "catch: %s", e); len(hand) > 1 {
m.TryCatch(msg, safe, hand[1:]...)
} else if !safe {
m.Assert(e)
@ -716,6 +720,14 @@ func (m *Message) Run(arg ...string) *Message {
m.target.server.Start(m, arg...)
return m
}
func (m *Message) Hold(n int) *Message {
if c := m.target; c.context != nil && c.context.wg != nil {
c.context.wg.Add(n)
} else {
c.root.wg.Add(n)
}
return m
}
func (m *Message) Done() bool {
defer func() { recover() }()
if m.target.context != nil && m.target.context.wg != nil {
@ -860,6 +872,10 @@ func (m *Message) Richs(key string, chain interface{}, raw interface{}, cb inter
case "*":
// 全部遍历
switch cb := cb.(type) {
case func(string, string):
for k, v := range hash {
cb(k, kit.Format(v))
}
case func(string, map[string]interface{}):
for k, v := range hash {
res = v.(map[string]interface{})