1
0
mirror of https://shylinux.com/x/ContextOS synced 2025-04-25 16:58:06 +08:00

opt code.upgrade

Change-Id: Id0e61e33f462938263712a3c9d0fcd1c35f105e0
This commit is contained in:
shaoying 2019-02-02 07:32:42 +08:00
parent d021087355
commit 1edf3227b9
8 changed files with 211 additions and 97 deletions

62
etc/boot.sh Executable file
View File

@ -0,0 +1,62 @@
#! /bin/bash
log() {
echo $*
}
prepare() {
log "prepare dir"
mkdir -p bin etc usr
mkdir -p var/log var/tmp var/run
}
dir=/usr/local/context
[ -d "$1" ] && dir=$1 && shift
[ -d "$dir" ] && cd $dir
bench=bench
[ -f bin/bench ] && bench=bin/bench
pid=`cat var/run/bench.pid`
case $1 in
help)
cat<<END
$0: context boot script
install: install context
restart: restart context
start: start context
stop: stop context
END
;;
install)
dev=$2
prepare
wget -O etc/exit.shy $2/code/upgrade/exit_shy
wget -O etc/init.shy $2/code/upgrade/init_shy
wget -O etc/common.shy $2/code/upgrade/common_shy
wget -O bin/bench $2/code/upgrade/bench && chmod u+x bin/bench
wget -O bin/boot.sh $2/code/upgrade/boot_sh && chmod u+x bin/boot.sh
;;
upgrade)
log "kill" usr1
kill -USR2 $pid
;;
start|"")
prepare
while true; do
pwd
log $bench
$bench 2>var/log/error.log && break
log "restarting..."
sleep 3
done
;;
stop)
log "kill" quit
kill -QUIT $pid
;;
restart)
log "kill" usr1
kill -USR1 $pid
;;
esac

View File

@ -54,6 +54,11 @@ func (cli *CLI) Spawn(m *ctx.Message, c *ctx.Context, arg ...string) ctx.Server
return &CLI{Context: c}
}
func (cli *CLI) Begin(m *ctx.Message, arg ...string) ctx.Server {
name, _ := os.Hostname()
m.Conf("runtime", "hostname", name)
m.Conf("runtime", "pid", os.Getpid())
m.Conf("runtime", "GOOS", runtime.GOOS)
m.Conf("runtime", "GOARCH", runtime.GOARCH)
return cli
}
func (cli *CLI) Start(m *ctx.Message, arg ...string) bool {
@ -98,6 +103,8 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心",
"nshell": &ctx.Cache{Name: "nshell", Value: "0", Help: "终端数量"},
},
Configs: map[string]*ctx.Config{
"runtime": &ctx.Config{Name: "runtime", Value: map[string]interface{}{}, Help: "运行环境"},
"init_shy": &ctx.Config{Name: "init_shy", Value: "etc/init.shy", Help: "启动脚本"},
"exit_shy": &ctx.Config{Name: "exit_shy", Value: "etc/exit.shy", Help: "启动脚本"},
"cmd_script": &ctx.Config{Name: "cmd_script", Value: map[string]interface{}{
@ -287,6 +294,14 @@ var Index = &ctx.Context{Name: "cli", Help: "管理中心",
}
return
}},
"exit": &ctx.Command{Name: "exit code", Help: "停止服务", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
m.Cmd("cli.source", m.Conf("exit_shy"))
go func() {
time.Sleep(time.Second * 3)
os.Exit(kit.Int(arg[0]))
}()
return
}},
"alias": &ctx.Command{Name: "alias [short [long...]]|[delete short]|[import module [command [alias]]]",
Help: "查看、定义或删除命令别名, short: 命令别名, long: 命令原名, delete: 删除别名, import导入模块所有命令",

View File

@ -82,12 +82,27 @@ func (gdb *GDB) Begin(m *ctx.Message, arg ...string) ctx.Server {
func (gdb *GDB) Start(m *ctx.Message, arg ...string) bool {
gdb.goon = make(chan os.Signal, 10)
gdb.wait = make(chan interface{}, 10)
signal.Notify(gdb.goon, syscall.Signal(30))
m.Confm("signal", func(sig string, action string) {
m.Log("signal", "add %s %s", sig, action)
signal.Notify(gdb.goon, syscall.Signal(kit.Int(sig)))
})
for {
select {
case sig := <-gdb.goon:
m.Log("error", "signal %v", sig)
gdb.Goon(nil, "cache", "read", "value")
action := m.Conf("signal", sig)
m.Log("signal", "signal %v %v", sig, action)
switch action {
case "quit":
m.Cmd("cli.exit", 0)
case "restart":
m.Cmd("cli.exit", 1)
case "upgrade":
m.Find("web.code").Cmd("upgrade", "system")
default:
// gdb.Goon(nil, "cache", "read", "value")
}
}
}
return true
@ -103,6 +118,11 @@ func (gdb *GDB) Close(m *ctx.Message, arg ...string) bool {
var Index = &ctx.Context{Name: "gdb", Help: "调试中心",
Caches: map[string]*ctx.Cache{},
Configs: map[string]*ctx.Config{
"signal": &ctx.Config{Name: "signal", Value: map[string]interface{}{
"3": "quit",
"10": "restart",
"12": "upgrade",
}, Help: "信号"},
"debug": &ctx.Config{Name: "debug", Value: map[string]interface{}{"value": map[string]interface{}{"enable": false},
"trace": map[string]interface{}{"value": map[string]interface{}{"enable": true}},
"context": map[string]interface{}{"value": map[string]interface{}{"enable": false},

View File

@ -119,7 +119,7 @@ var Index = &ctx.Context{Name: "log", Help: "日志中心",
},
Configs: map[string]*ctx.Config{
"logdir": &ctx.Config{Name: "logdir", Value: "var/log", Help: ""},
"logpid": &ctx.Config{Name: "logpid", Value: "var/log/bench.pid", Help: ""},
"logpid": &ctx.Config{Name: "logpid", Value: "var/run/bench.pid", Help: ""},
"output": &ctx.Config{Name: "output", Value: map[string]interface{}{
"error": map[string]interface{}{"value": map[string]interface{}{"file": "error.log", "meta": []interface{}{"time", "ship"}, "color_begin": "\033[31m", "color_end": "\033[0m"}},
"trace": map[string]interface{}{"value": map[string]interface{}{"file": "error.log", "meta": []interface{}{"time", "ship"}, "color_begin": "\033[32m", "color_end": "\033[0m"}},

View File

@ -34,26 +34,26 @@ func (ssh *SSH) Close(m *ctx.Message, arg ...string) bool {
var Index = &ctx.Context{Name: "ssh", Help: "集群中心",
Caches: map[string]*ctx.Cache{
"nhost": &ctx.Cache{Name: "nhost", Value: "0", Help: "主机数量"},
"hostname": &ctx.Cache{Name: "hostname", Value: "shy", Help: "本机域名"},
"nnode": &ctx.Cache{Name: "nnode", Value: "0", Help: "节点数量"},
"nodename": &ctx.Cache{Name: "nodename", Value: "shy", Help: "本机域名"},
},
Configs: map[string]*ctx.Config{
"host": &ctx.Config{Name: "host", Value: map[string]interface{}{}, Help: "主机信息"},
"node": &ctx.Config{Name: "node", Value: map[string]interface{}{}, Help: "主机信息"},
"hostport": &ctx.Config{Name: "hostport", Value: "", Help: "主机域名"},
"hostname": &ctx.Config{Name: "hostname", Value: "com", Help: "主机域名"},
"nodename": &ctx.Config{Name: "nodename", Value: "com", Help: "主机域名"},
"current": &ctx.Config{Name: "current", Value: "", Help: "当前主机"},
"timer": &ctx.Config{Name: "timer", Value: "", Help: "当前主机"},
},
Commands: map[string]*ctx.Command{
"remote": &ctx.Command{Name: "remote listen|dial args...", Help: "远程连接", Form: map[string]int{"right": 1, "hostname": 1}, Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
"remote": &ctx.Command{Name: "remote listen|dial args...", Help: "远程连接", Form: map[string]int{"right": 1, "nodename": 1}, Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
if len(arg) == 0 { // 查看主机
m.Cmdy("ctx.config", "host")
m.Cmdy("ctx.config", "node")
return
}
switch arg[0] {
case "redial": // 断线重连
if !m.Caps("hostname") {
if !m.Caps("nodename") {
m.Cmdx("remote", "dial", arg[1:])
}
case "listen", "dial":
@ -66,8 +66,8 @@ var Index = &ctx.Context{Name: "ssh", Help: "集群中心",
m.Conf("timer", m.Cmdx("cli.timer", "delete", m.Conf("timer")))
}
m.Spawn(nfs.Target()).Call(func(host *ctx.Message) *ctx.Message {
m.Confv("host", host.Result(1), map[string]interface{}{ // 添加主机
m.Spawn(nfs.Target()).Call(func(node *ctx.Message) *ctx.Message {
m.Confv("node", node.Result(1), map[string]interface{}{ // 添加主机
"module": nfs.Format("target"),
"create_time": m.Time(),
"access_time": m.Time(),
@ -76,42 +76,42 @@ var Index = &ctx.Context{Name: "ssh", Help: "集群中心",
})
m.Cap("stream", nfs.Format("target"))
m.Cap("hostname", host.Result(0))
m.Cap("nodename", node.Result(0))
if !m.Confs("current") {
m.Conf("current", host.Result(1))
m.Conf("current", node.Result(1))
}
nfs.Free(func(nfs *ctx.Message) bool { // 连接中断
m.Conf("timer", m.Cmdx("cli.timer", "repeat", "10s", "context", "ssh", "remote", "redial", arg[1:]))
m.Log("info", "delete host %s", host.Result(1))
delete(m.Confm("host"), host.Result(1))
m.Cap("hostname", "")
m.Log("info", "delete node %s", node.Result(1))
delete(m.Confm("node"), node.Result(1))
m.Cap("nodename", "")
m.Cap("stream", "")
return true
})
return nil
}, "send", "recv", "add", m.Confx("hostname"))
}, "send", "recv", "add", m.Confx("nodename"))
}
return nil
}, "nfs.remote", arg)
case "recv":
switch arg[1] {
case "add":
if host := m.Confm("host", arg[2]); host == nil { // 添加主机
m.Confv("host", arg[2], map[string]interface{}{
if node := m.Confm("node", arg[2]); node == nil { // 添加主机
m.Confv("node", arg[2], map[string]interface{}{
"module": m.Format("source"),
"create_time": m.Time(),
"access_time": m.Time(),
"username": m.Option("right"),
"cm_target": "ctx.web.code",
})
} else if len(arg) > 3 && arg[3] == kit.Format(host["token"]) { // 断线重连
host["access_time"] = m.Time()
host["module"] = m.Format("source")
} else if len(arg) > 3 && arg[3] == kit.Format(node["token"]) { // 断线重连
node["access_time"] = m.Time()
node["module"] = m.Format("source")
} else { // 域名冲突
arg[2] = fmt.Sprintf("%s_%d", arg[2], m.Capi("nhost", 1))
m.Confv("host", arg[2], map[string]interface{}{
arg[2] = fmt.Sprintf("%s_%d", arg[2], m.Capi("nnode", 1))
m.Confv("node", arg[2], map[string]interface{}{
"module": m.Format("source"),
"create_time": m.Time(),
"access_time": m.Time(),
@ -124,10 +124,10 @@ var Index = &ctx.Context{Name: "ssh", Help: "集群中心",
m.Conf("current", arg[2])
}
m.Echo(arg[2]).Echo(m.Cap("hostname")).Back(m)
m.Echo(arg[2]).Echo(m.Cap("nodename")).Back(m)
m.Sess("ms_source", false).Free(func(msg *ctx.Message) bool { // 断线清理
m.Log("info", "delete host %s", arg[2])
delete(m.Confm("host"), arg[2])
m.Log("info", "delete node %s", arg[2])
delete(m.Confm("node"), arg[2])
return true
})
}
@ -136,23 +136,23 @@ var Index = &ctx.Context{Name: "ssh", Help: "集群中心",
names, arg := strings.SplitN(arg[0], ".", 2), arg[1:]
if names[0] == "" { // 本地执行
host := m.Confm("host", m.Option("hostname"))
user := kit.Format(kit.Chain(host, "username"))
node := m.Confm("node", m.Option("nodename"))
user := kit.Format(kit.Chain(node, "username"))
sessid := m.Cmd("aaa.user", user, "ssh").Append("meta")
sessid := m.Cmd("aaa.user", user, "ssh").Append("key")
if sessid == "" { // 创建会话
sessid = m.Cmdx("aaa.sess", "ssh", "ip", "what")
m.Cmd("aaa.sess", sessid, user, "ppid", "what")
}
bench := m.Cmd("aaa.sess", sessid, "bench").Append("meta")
bench := m.Cmd("aaa.sess", sessid, "bench").Append("key")
if bench == "" { // 创建空间
bench = m.Cmdx("aaa.work", sessid, "ssh")
}
if m.Cmds("aaa.work", bench, "right", user, "remote", arg[0]) { // 执行命令
msg := m.Find(m.Option("current_ctx", kit.Format(host["cm_target"]))).Cmd(arg).CopyTo(m)
host["cm_target"] = msg.Cap("module")
msg := m.Find(m.Option("current_ctx", kit.Format(node["cm_target"]))).Cmd(arg).CopyTo(m)
node["cm_target"] = msg.Cap("module")
} else {
m.Echo("no right %s %s", "remote", arg[0])
}
@ -170,17 +170,17 @@ var Index = &ctx.Context{Name: "ssh", Help: "集群中心",
}
rest := kit.Select("", names, 1)
m.Option("hostname", m.Cap("hostname"))
m.Option("nodename", m.Cap("nodename"))
if names[0] == "*" { // 广播命令
m.Confm("host", func(name string, host map[string]interface{}) {
m.Find(kit.Format(host["module"]), true).Copy(m, "option").CallBack(sync, func(sub *ctx.Message) *ctx.Message {
m.Confm("node", func(name string, node map[string]interface{}) {
m.Find(kit.Format(node["module"]), true).Copy(m, "option").CallBack(sync, func(sub *ctx.Message) *ctx.Message {
return m.Copy(sub, "append").Copy(sub, "result")
}, "send", "", arg)
})
} else if m.Confm("host", names[0], func(host map[string]interface{}) { // 单播命令
m.Find(kit.Format(host["module"]), true).Copy(m, "option").CallBack(sync, func(sub *ctx.Message) *ctx.Message {
} else if m.Confm("node", names[0], func(node map[string]interface{}) { // 单播命令
m.Find(kit.Format(node["module"]), true).Copy(m, "option").CallBack(sync, func(sub *ctx.Message) *ctx.Message {
return m.Copy(sub, "append").Copy(sub, "result")
}, "send", rest, arg)
@ -192,16 +192,16 @@ var Index = &ctx.Context{Name: "ssh", Help: "集群中心",
}
return
}},
"sh": &ctx.Command{Name: "sh [[host] name] cmd...", Help: "发送命令", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
"sh": &ctx.Command{Name: "sh [[node] name] cmd...", Help: "发送命令", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
if len(arg) == 0 {
m.Echo(m.Conf("current"))
return
}
if arg[0] == "host" {
if arg[0] == "node" {
m.Conf("current", arg[1])
arg = arg[2:]
} else if m.Confm("host", arg[0]) != nil {
} else if m.Confm("node", arg[0]) != nil {
m.Conf("current", arg[0])
arg = arg[1:]
}
@ -211,16 +211,16 @@ var Index = &ctx.Context{Name: "ssh", Help: "集群中心",
m.Copy(msg, "result")
return
}},
"cp": &ctx.Command{Name: "cp [[host] name] filename", Help: "发送文件", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
"cp": &ctx.Command{Name: "cp [[node] name] filename", Help: "发送文件", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
if len(arg) == 0 {
m.Echo(m.Conf("current"))
return
}
if arg[0] == "host" {
if arg[0] == "node" {
m.Conf("current", arg[1])
arg = arg[2:]
} else if m.Confm("host", arg[0]) != nil {
} else if m.Confm("node", arg[0]) != nil {
m.Conf("current", arg[0])
arg = arg[1:]
}

View File

@ -142,6 +142,20 @@ func (web *WEB) HandleCmd(m *ctx.Message, key string, cmd *ctx.Command) {
msg.Option("path", r.URL.Path)
msg.Optionv("debug", false)
agent := r.Header.Get("User-Agent")
switch {
case strings.Contains(agent, "Macintosh"):
msg.Option("GOOS", "darwin")
default:
msg.Option("GOOS", "linux")
}
switch {
case strings.Contains(agent, "Intel"):
msg.Option("GOARCH", "386")
default:
msg.Option("GOARCH", "386")
}
msg.Option("dir_root", msg.Cap("directory"))
for _, v := range r.Cookies() {
msg.Option(v.Name, v.Value)
@ -553,7 +567,7 @@ var Index = &ctx.Context{Name: "web", Help: "应用中心",
var result interface{}
ct := res.Header.Get("Content-Type")
parse := kit.Select(kit.Format(client["parse"]), m.Option("parse"))
m.Log("info", "parse: %s content: %s", parse, ct)
m.Log("info", "status %s parse: %s content: %s", res.Status, parse, ct)
switch {
case parse == "json" || strings.HasPrefix(ct, "application/json") || strings.HasPrefix(ct, "application/javascript"):

View File

@ -7,7 +7,7 @@ import (
"net/http"
"os"
"strconv"
"time"
"strings"
)
var Index = &ctx.Context{Name: "code", Help: "代码中心",
@ -215,14 +215,65 @@ var Index = &ctx.Context{Name: "code", Help: "代码中心",
}, Help: "组件列表"},
"upgrade": &ctx.Config{Name: "upgrade", Value: map[string]interface{}{
"file": map[string]interface{}{
"boot_sh": "bin/boot.sh",
"bench": "bin/bench.new",
"init_shy": "etc/init.shy",
"common_shy": "etc/common.shy",
"exit_shy": "etc/exit.shy",
"bench": "bin/bench.new",
},
}, Help: "日志地址"},
},
Commands: map[string]*ctx.Command{
"update": &ctx.Command{Name: "update", Help: "更新代码", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
return
}},
"/upgrade/": &ctx.Command{Name: "/upgrade/", Help: "下载文件", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
p := m.Cmdx("nfs.path", key)
if strings.HasSuffix(key, "/bench") {
bench := m.Cmdx("nfs.path", key+"."+m.Option("GOOS")+"."+m.Option("GOARCH"))
if _, e := os.Stat(bench); e == nil {
p = bench
}
}
m.Log("info", "upgrade %s %s", p, m.Cmdx("aaa.hash", "file", p))
http.ServeFile(m.Optionv("response").(http.ResponseWriter), m.Optionv("request").(*http.Request), p)
return
}},
"upgrade": &ctx.Command{Name: "upgrade system|script", Help: "服务升级", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
if len(arg) == 0 {
m.Cmdy("ctx.config", "upgrade", "file")
return
}
if arg[0] == "system" {
arg = arg[1:]
m.Confm("upgrade", "file", func(key string, value string) {
arg = append(arg, key)
})
}
restart := false
for _, link := range arg {
if file := m.Conf("upgrade", []string{"file", link}); file != "" {
if m.Cmd("web.get", "dev", fmt.Sprintf("code/upgrade/%s", link), "save", file); strings.HasPrefix(file, "bin/") {
if m.Cmd("cli.system", "chmod", "u+x", file); link == "bench" {
m.Cmd("cli.system", "mv", "bin/bench", fmt.Sprintf("bin/bench_%s", m.Time("20060102_150405")))
m.Cmd("cli.system", "mv", "bin/bench.new", "bin/bench")
}
}
restart = true
} else {
m.Cmdy("web.get", "dev", fmt.Sprintf("code/upgrade/script/%s", link), "save", fmt.Sprintf("usr/script/%s", link))
}
}
if restart {
m.Cmd("cli.exit", 1)
}
return
}},
"/counter": &ctx.Command{Name: "/counter", Help: "/counter", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
if len(arg) > 0 {
m.Option("name", arg[0])
@ -248,54 +299,6 @@ var Index = &ctx.Context{Name: "code", Help: "代码中心",
}
return
}},
"/upgrade/": &ctx.Command{Name: "/upgrade/", Help: "下载文件", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
r := m.Optionv("request").(*http.Request)
w := m.Optionv("response").(http.ResponseWriter)
p := m.Cmdx("nfs.path", key)
m.Log("info", "upgrade %s %s", p, m.Cmdx("aaa.hash", "file", p))
http.ServeFile(w, r, p)
return
}},
"upgrade": &ctx.Command{Name: "upgrade system|script", Help: "服务升级", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
if len(arg) == 0 {
m.Cmdy("ctx.config", "upgrade", "file")
return
}
if arg[0] == "system" {
m.Cmd("cli.source", m.Conf("exit.shy"))
m.Confm("upgrade", "file", func(key string, value string) {
m.Cmd("web.get", "dev", fmt.Sprintf("code/upgrade/%s", key), "save", value)
})
m.Cmd("cli.system", "chmod", "u+x", "bin/bench.new")
m.Cmd("cli.system", "mv", "bin/bench", fmt.Sprintf("bin/bench_%s", m.Time("20060102_150405")))
m.Cmd("cli.system", "mv", "bin/bench.new", "bin/bench")
go func() {
time.Sleep(time.Second * 3)
os.Exit(1)
}()
return
}
if file := m.Conf("upgrade", []string{"file", arg[0]}); file != "" {
m.Cmd("web.get", "dev", fmt.Sprintf("code/upgrade/%s", arg[0]), "save", file)
if arg[0] == "bench" {
m.Cmd("cli.system", "chmod", "u+x", "bin/bench.new")
m.Cmd("cli.system", "mv", "bin/bench", fmt.Sprintf("bin/bench_%s", m.Time("20060102_150405")))
m.Cmd("cli.system", "mv", "bin/bench.new", "bin/bench")
}
go func() {
time.Sleep(time.Second * 3)
os.Exit(1)
}()
return
}
m.Cmdy("web.get", "dev", fmt.Sprintf("code/upgrade/script/%s", arg[0]), "save", fmt.Sprintf("usr/script/%s", arg[0]), arg[1:])
return
}},
"/consul": &ctx.Command{Name: "/consul", Help: "下载文件", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
m.Append("hostport", m.Cmdx("ssh.config", "hostport"))
return

BIN
usr/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.4 KiB