1
0
mirror of https://shylinux.com/x/icebergs synced 2025-04-26 01:24:05 +08:00

opt ssh.connect

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

View File

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

View File

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

View File

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

View File

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

View File

@ -20,7 +20,7 @@ func (f *Frame) Spawn(m *ice.Message, c *ice.Context, arg ...string) ice.Server
return &Frame{}
}
func (f *Frame) Begin(m *ice.Message, arg ...string) ice.Server {
f.t = time.Tick(kit.Duration(m.Cap(ice.CTX_STREAM, ice.MOD_TICK)))
f.t = time.Tick(kit.Duration(m.Conf(TIMER, kit.Keym("tick"))))
f.s = make(chan os.Signal, ice.MOD_CHAN)
f.e = make(chan bool, 1)
return f
@ -65,7 +65,8 @@ const GDB = "gdb"
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) {
m.Cmd(nfs.SAVE, kit.Select(m.Conf(SIGNAL, kit.META_PATH), m.Conf(cli.RUNTIME, "conf.ctx_pid")), m.Conf(cli.RUNTIME, "host.pid"))
m.Cmd(nfs.SAVE, kit.Select(m.Conf(SIGNAL, kit.META_PATH), m.Conf(cli.RUNTIME, kit.Keys(cli.CONF, cli.CTX_PID))),
m.Conf(cli.RUNTIME, kit.Keys(cli.HOST, "pid")))
m.Cmd(SIGNAL, LISTEN, SIGNAL, "3", kit.MDB_NAME, "退出", kit.SSH_CMD, "exit 0")
m.Cmd(SIGNAL, LISTEN, SIGNAL, "2", kit.MDB_NAME, "重启", kit.SSH_CMD, "exit 1")

View File

@ -1,7 +1,9 @@
package gdb
import (
"os"
"os/signal"
"path"
"syscall"
ice "github.com/shylinux/icebergs"
@ -23,6 +25,18 @@ func _signal_action(m *ice.Message, s int) {
})
}
func SignalNotify(m *ice.Message, sig int, cb func()) {
ch := make(chan os.Signal)
signal.Notify(ch, syscall.Signal(sig))
m.Go(func() {
for {
if _, ok := <-ch; ok {
cb()
}
}
})
}
const (
LISTEN = "listen"
ACTION = "action"
@ -33,7 +47,7 @@ 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,
kit.MDB_PATH, path.Join(ice.VAR_RUN, "ice.pid"), kit.MDB_SHORT, SIGNAL,
)},
},
Commands: map[string]*ice.Command{

View File

@ -9,7 +9,7 @@ import (
)
func _timer_create(m *ice.Message, arg ...string) {
m.Cmdy(mdb.INSERT, TIMER, "", mdb.HASH, "delay", "10ms", "interval", "10m", "order", 1, "next", m.Time(m.Option("delay")), arg)
m.Cmdy(mdb.INSERT, TIMER, "", mdb.HASH, DELAY, "10ms", INTERVAL, "10m", ORDER, 1, NEXT, m.Time(m.Option(DELAY)), arg)
}
func _timer_action(m *ice.Message, arg ...string) {
now := time.Now().UnixNano()
@ -20,19 +20,25 @@ func _timer_action(m *ice.Message, arg ...string) {
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)
order := kit.Int(value[ORDER])
if n := kit.Time(kit.Format(value[NEXT])); now > n && order > 0 {
m.Logs(TIMER, kit.MDB_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"])
if value[ORDER] = kit.Format(order - 1); order > 1 {
value[NEXT] = msg.Time(value[INTERVAL])
}
}
})
}
const (
DELAY = "delay"
INTERVAL = "interval"
ORDER = "order"
NEXT = "next"
)
const TIMER = "timer"
func init() {
@ -53,7 +59,7 @@ func init() {
}},
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)
m.Cmdy(mdb.PRUNES, TIMER, "", mdb.HASH, ORDER, 0)
}},
ACTION: {Name: "action", Help: "执行", Hand: func(m *ice.Message, arg ...string) {

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,13 +1,13 @@
package ice
import (
kit "github.com/shylinux/toolkits"
"github.com/shylinux/toolkits/task"
"errors"
"fmt"
"io"
"time"
kit "github.com/shylinux/toolkits"
"github.com/shylinux/toolkits/task"
)
func (m *Message) TryCatch(msg *Message, safe bool, hand ...func(msg *Message)) *Message {