From aad9c09e96351f250f31b2c57fa1826091396261 Mon Sep 17 00:00:00 2001 From: shy Date: Tue, 5 Dec 2023 04:03:44 +0800 Subject: [PATCH] opt ssh/connect.go --- base/cli/system.go | 1 + base/mdb/hash.go | 7 ++++ base/tcp/client.go | 3 +- base/web/html/html.go | 30 +++++++++++----- base/web/option.go | 2 +- base/web/render.go | 2 ++ base/web/space.go | 2 ++ meta.go | 6 ++++ misc/ssh/connect.go | 79 ++++++++++++++++++++++++++++++++++++++++--- 9 files changed, 117 insertions(+), 15 deletions(-) diff --git a/base/cli/system.go b/base/cli/system.go index 6bc89cca..ca27a00e 100644 --- a/base/cli/system.go +++ b/base/cli/system.go @@ -143,6 +143,7 @@ const ( FIND = "find" GREP = "grep" EXEC = "exec" + EXIT = "exit" ECHO = "echo" REST = "rest" OPENS = "opens" diff --git a/base/mdb/hash.go b/base/mdb/hash.go index e83e1450..65d2e3fd 100644 --- a/base/mdb/hash.go +++ b/base/mdb/hash.go @@ -231,6 +231,13 @@ func HashSelect(m *ice.Message, arg ...string) *ice.Message { if m.PushAction(Config(m, ACTION), REMOVE); !m.FieldsIsDetail() { return m.Action(CREATE, PRUNES) } + if m.FieldsIsDetail() { + m.Table(func(value ice.Maps) { + m.SetAppend().OptionFields(ice.FIELDS_DETAIL) + kit.For(kit.Split(HashField(m)), func(key string) { m.Push(key, value[key]); delete(value, key) }) + kit.For(kit.SortedKey(value), func(k string) { m.Push(k, value[k]) }) + }) + } return m } func HashPrunes(m *ice.Message, cb func(Map) bool) *ice.Message { diff --git a/base/tcp/client.go b/base/tcp/client.go index 84ae793f..5c556888 100644 --- a/base/tcp/client.go +++ b/base/tcp/client.go @@ -2,6 +2,7 @@ package tcp import ( "net" + "time" ice "shylinux.com/x/icebergs" "shylinux.com/x/icebergs/base/mdb" @@ -29,7 +30,7 @@ func (c *Conn) Write(b []byte) (int, error) { func (c *Conn) Close() error { return c.Conn.Close() } func _client_dial(m *ice.Message, arg ...string) { - c, e := net.Dial(TCP, m.Option(HOST)+nfs.DF+m.Option(PORT)) + c, e := net.DialTimeout(TCP, m.Option(HOST)+nfs.DF+m.Option(PORT), 3*time.Second) c = &Conn{Conn: c, m: m, s: &Stat{}} defer kit.If(e == nil, func() { c.Close() }) switch cb := m.OptionCB("").(type) { diff --git a/base/web/html/html.go b/base/web/html/html.go index 3539ea34..0fd8967f 100644 --- a/base/web/html/html.go +++ b/base/web/html/html.go @@ -7,9 +7,18 @@ import ( ) const ( - H1 = "h1" - H2 = "h2" - H3 = "h3" + H1 = "h1" + H2 = "h2" + H3 = "h3" + SPAN = "span" + + STYLE = "style" + WIDTH = "width" + HEIGHT = "height" + + BACKGROUND_COLOR = "background-color" + + COLOR = "color" ) const ( DARK = "dark" @@ -30,11 +39,6 @@ const ( LAYOUT = "layout" RESIZE = "resize" FILTER = "filter" - HEIGHT = "height" - WIDTH = "width" - - COLOR = "color" - BACKGROUND_COLOR = "background-color" ) const ( @@ -63,3 +67,13 @@ const ( Record1 = "record1" Record2 = "record2" ) + +func Format(tag string, inner string, arg ...string) string { + return kit.Format("<%s %s>%s", tag, kit.JoinProperty(arg...), inner, tag) +} +func FormatDanger(value string) string { + return Format(SPAN, value, STYLE, kit.JoinCSS( + BACKGROUND_COLOR, "var(--danger-bg-color)", + COLOR, "var(--danger-fg-color)", + )) +} diff --git a/base/web/option.go b/base/web/option.go index 51235584..c96ada2d 100644 --- a/base/web/option.go +++ b/base/web/option.go @@ -103,7 +103,7 @@ func PushImages(m *ice.Message, name string) { } func PushNotice(m *ice.Message, arg ...ice.Any) { opts := ice.Map{ice.MSG_OPTION: []string{}, ice.MSG_OPTS: []string{}} - kit.For([]string{ice.LOG_DEBUG, ice.LOG_TRACEID}, func(key string) { + kit.For([]string{ctx.DISPLAY, ctx.STYLE, ice.LOG_DEBUG, ice.LOG_TRACEID}, func(key string) { opts[ice.MSG_OPTION] = kit.Simple(opts[ice.MSG_OPTION], key) opts[key] = m.Option(key) }) diff --git a/base/web/render.go b/base/web/render.go index 32fcd5d7..346eb651 100644 --- a/base/web/render.go +++ b/base/web/render.go @@ -188,4 +188,6 @@ const ( CHAT_FLOWS = "web.chat.flows" CHAT_GRANT = "web.chat.grant" TEAM_PLAN = "web.team.plan" + + PLUGIN_XTERM = "/plugin/local/code/xterm.js" ) diff --git a/base/web/space.go b/base/web/space.go index 906b8ef1..000161b4 100644 --- a/base/web/space.go +++ b/base/web/space.go @@ -190,6 +190,8 @@ func init() { m.Cmdy(tcp.WIFI).CutTo(tcp.SSID, arg[0]) case mdb.ICON: m.Cmdy(nfs.DIR, ice.USR_ICONS, nfs.PATH).CutTo(nfs.PATH, arg[0]) + case aaa.PASSWORD: + m.SetAppend() case ctx.INDEX: if space := m.Option(SPACE); space != "" { m.Options(SPACE, []string{}).Cmdy(SPACE, space, ctx.COMMAND) diff --git a/meta.go b/meta.go index 6a8ff60d..7ac2948f 100644 --- a/meta.go +++ b/meta.go @@ -152,6 +152,12 @@ func (m *Message) Copy(msg *Message, arg ...string) *Message { return m.Add(MSG_RESULT, msg.value(MSG_RESULT)...) } func (m *Message) Length() (max int) { + if m.FieldsIsDetail() { + if len(m.value(KEY)) > 0 { + return 1 + } + return 0 + } kit.For(m.value(MSG_APPEND), func(k string) { max = kit.Max(len(m.value(k)), max) }) return max } diff --git a/misc/ssh/connect.go b/misc/ssh/connect.go index 745e389e..37b7bfb5 100644 --- a/misc/ssh/connect.go +++ b/misc/ssh/connect.go @@ -5,7 +5,9 @@ import ( "io" "net" "os" + "path" "strings" + "time" "golang.org/x/crypto/ssh" "golang.org/x/crypto/ssh/terminal" @@ -24,6 +26,7 @@ import ( "shylinux.com/x/icebergs/core/code" "shylinux.com/x/icebergs/misc/xterm" kit "shylinux.com/x/toolkits" + "shylinux.com/x/toolkits/task" ) func _ssh_open(m *ice.Message, arg ...string) { @@ -38,9 +41,7 @@ func _ssh_open(m *ice.Message, arg ...string) { defer c.Write([]byte(cmd + lex.NL)) m.Sleep300ms() }) - m.Go(func() { - io.Copy(c, os.Stdin) - }) + m.Go(func() { io.Copy(c, os.Stdin) }) io.Copy(os.Stdout, c) }, arg...) } @@ -70,11 +71,11 @@ func _ssh_dial(m *ice.Message, cb func(net.Conn), arg ...string) { fmt.Sscanf(string(buf[:n]), "#height:%d,width:%d", &h, &w) } m.Go(func() { - defer c.Close() s, e := client.NewSession() if e != nil { return } + defer c.Close() s.Stdin, s.Stdout, s.Stderr = c, c, c s.RequestPty(kit.Env(cli.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())); s.WindowChange(h, w) }) @@ -93,7 +94,7 @@ func _ssh_dial(m *ice.Message, cb func(net.Conn), arg ...string) { func _ssh_conn(m *ice.Message, cb func(*ssh.Client), arg ...string) { methods := []ssh.AuthMethod{} methods = append(methods, ssh.PublicKeysCallback(func() ([]ssh.Signer, error) { - key, err := ssh.ParsePrivateKey([]byte(m.Cmdx(nfs.CAT, kit.HomePath(m.Option(PRIVATE))))) + key, err := ssh.ParsePrivateKey([]byte(m.Cmdx(nfs.CAT, kit.HomePath(m.OptionDefault(PRIVATE, ".ssh/id_rsa"))))) return []ssh.Signer{key}, err })) methods = append(methods, ssh.PasswordCallback(func() (string, error) { return m.Option(aaa.PASSWORD), nil })) @@ -228,3 +229,71 @@ func (s session) Read(buf []byte) (int, error) { return s.pty.Read(buf) } func (s session) Close() error { return s.sess.Close() } func init() { xterm.AddCommand(SSH, NewSession) } +func CombinedOutput(m *ice.Message, cmd string, cb func(string)) { + _ssh_conn(m, func(c *ssh.Client) { + if s, e := c.NewSession(); !m.Warn(e, ice.ErrNotValid) { + defer s.Close() + m.Debug("cmd %v", cmd) + if b, e := s.CombinedOutput(cmd); !m.Warn(e, ice.ErrNotValid) { + cb(string(b)) + } + } + }) +} +func PushOutput(m *ice.Message, cmd string, cb func(string)) { + _ssh_conn(m, func(c *ssh.Client) { + if s, e := c.NewSession(); !m.Warn(e, ice.ErrNotValid) { + defer s.Close() + r, _ := s.StdoutPipe() + m.Debug("res %v", cmd) + s.Run(cmd) + kit.For(r, func(res []byte) { + m.Debug("res %v", string(res)) + cb(string(res)) + }) + } + }) +} +func PushShell(m *ice.Message, cmds []string, cb func(string)) { + _ssh_conn(m, func(c *ssh.Client) { + if s, e := c.NewSession(); !m.Warn(e, ice.ErrNotValid) { + defer s.Close() + w, _ := s.StdinPipe() + r, _ := s.StdoutPipe() + width, height, _ := terminal.GetSize(int(os.Stdin.Fd())) + s.RequestPty(kit.Env(cli.TERM), height, width, ssh.TerminalModes{ssh.ECHO: 1, ssh.TTY_OP_ISPEED: 14400, ssh.TTY_OP_OSPEED: 14400}) + defer s.Wait() + s.Shell() + lock := task.Lock{} + list := [][]string{} + cmd := kit.Format("%s@%s[%s]%s$ ssh %s@%s\r\n", + m.Option(aaa.USERNAME), ice.Info.Hostname, kit.Split(time.Now().Format(ice.MOD_TIME))[1], path.Base(kit.Path("")), + m.Option(aaa.USERNAME), m.Option(tcp.HOST)) + list = append(list, []string{cmd}) + m.Debug("cmd %v", cmd) + cb(cmd) + defer cb("\r\n\r\n") + m.Go(func() { + kit.For(append(cmds, cli.EXIT), func(cmd string) { + for { + m.Sleep300ms() + if func() bool { defer lock.Lock()(); return len(list[len(list)-1]) > 1 }() { + break + } + } + m.Debug("cmd %v", cmd) + fmt.Fprintln(w, cmd) + defer lock.Lock()() + list = append(list, []string{cmd}) + }) + }) + kit.For(r, func(res []byte) { + m.Debug("res %v", string(res)) + m.Debug("res %v", res) + cb(string(res)) + defer lock.Lock()() + list[len(list)-1] = append(list[len(list)-1], string(res)) + }) + } + }) +}