mirror of
https://shylinux.com/x/icebergs
synced 2025-04-26 01:24:05 +08:00
opt ssh
This commit is contained in:
parent
4bbdd8d9e4
commit
bf34e9ceee
@ -62,6 +62,10 @@ func _hash_delete(m *ice.Message, prefix, chain, field, value string) {
|
||||
defer Lock(m, prefix, chain)()
|
||||
|
||||
Richs(m, prefix, chain, value, func(key string, val Map) {
|
||||
if target, ok := kit.GetMeta(val)[TARGET].(io.Closer); ok {
|
||||
m.Logs("close", target)
|
||||
target.Close()
|
||||
}
|
||||
m.Logs(DELETE, KEY, path.Join(prefix, chain), field, value, VALUE, kit.Format(val))
|
||||
m.Conf(prefix, kit.Keys(chain, HASH, key), "")
|
||||
})
|
||||
|
@ -182,9 +182,9 @@ func ZoneCreate(m *ice.Message, arg ...Any) {
|
||||
m.Cmdy(INSERT, m.PrefixKey(), "", HASH, arg)
|
||||
}
|
||||
func ZoneRemove(m *ice.Message, arg ...Any) {
|
||||
args := kit.Simple(arg)
|
||||
args := kit.Simple(arg...)
|
||||
if len(args) == 0 {
|
||||
args = m.OptionSimple(ZoneShort(m))
|
||||
args = m.OptionSimple(ZoneShort(m), HASH)
|
||||
} else if len(args) == 1 {
|
||||
args = []string{ZoneShort(m), args[0]}
|
||||
}
|
||||
|
@ -87,6 +87,7 @@ const (
|
||||
)
|
||||
const DEFS = "defs"
|
||||
const SAVE = "save"
|
||||
const LOAD = "load"
|
||||
const PUSH = "push"
|
||||
const COPY = "copy"
|
||||
const LINK = "link"
|
||||
|
@ -5,14 +5,15 @@ import (
|
||||
"io"
|
||||
"net"
|
||||
"os"
|
||||
"path"
|
||||
"strings"
|
||||
|
||||
"golang.org/x/crypto/ssh"
|
||||
"golang.org/x/crypto/ssh/terminal"
|
||||
|
||||
ice "shylinux.com/x/icebergs"
|
||||
"shylinux.com/x/icebergs/base/aaa"
|
||||
"shylinux.com/x/icebergs/base/cli"
|
||||
"shylinux.com/x/icebergs/base/ctx"
|
||||
"shylinux.com/x/icebergs/base/gdb"
|
||||
"shylinux.com/x/icebergs/base/mdb"
|
||||
"shylinux.com/x/icebergs/base/nfs"
|
||||
@ -44,10 +45,10 @@ func _ssh_open(m *ice.Message, arg ...string) {
|
||||
}, arg...)
|
||||
}
|
||||
func _ssh_dial(m *ice.Message, cb func(net.Conn), arg ...string) {
|
||||
p := path.Join(kit.Env(cli.HOME), ".ssh/", fmt.Sprintf("%s@%s:%s", m.Option(aaa.USERNAME), m.Option(tcp.HOST), m.Option(tcp.PORT)))
|
||||
if nfs.FileExists(m, p) {
|
||||
p := kit.HomePath(".ssh", fmt.Sprintf("%s@%s:%s", m.Option(aaa.USERNAME), m.Option(tcp.HOST), m.Option(tcp.PORT)))
|
||||
if nfs.ExistsFile(m, p) {
|
||||
if c, e := net.Dial("unix", p); e == nil {
|
||||
cb(c) // 会话连接
|
||||
cb(c) // 会话复用
|
||||
return
|
||||
}
|
||||
nfs.Remove(m, p)
|
||||
@ -75,28 +76,21 @@ func _ssh_dial(m *ice.Message, cb func(net.Conn), arg ...string) {
|
||||
m.Go(func() {
|
||||
defer c.Close()
|
||||
|
||||
session, e := client.NewSession()
|
||||
s, e := client.NewSession()
|
||||
if e != nil {
|
||||
return
|
||||
}
|
||||
|
||||
session.Stdin = c
|
||||
session.Stdout = c
|
||||
session.Stderr = c
|
||||
|
||||
session.RequestPty(kit.Env("TERM"), h, w, ssh.TerminalModes{
|
||||
ssh.ECHO: 1,
|
||||
ssh.TTY_OP_ISPEED: 14400,
|
||||
ssh.TTY_OP_OSPEED: 14400,
|
||||
})
|
||||
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})
|
||||
defer s.Wait()
|
||||
|
||||
gdb.SignalNotify(m, 28, func() {
|
||||
w, h, _ := terminal.GetSize(int(os.Stdin.Fd()))
|
||||
session.WindowChange(h, w)
|
||||
s.WindowChange(h, w)
|
||||
})
|
||||
|
||||
session.Shell()
|
||||
session.Wait()
|
||||
s.Shell()
|
||||
})
|
||||
}(c)
|
||||
}
|
||||
@ -118,7 +112,6 @@ func _ssh_conn(m *ice.Message, cb func(*ssh.Client), arg ...string) {
|
||||
if verify := m.Option("verify"); verify == "" {
|
||||
fmt.Printf(q)
|
||||
fmt.Scanf("%s\n", &verify)
|
||||
|
||||
res = append(res, verify)
|
||||
} else {
|
||||
res = append(res, aaa.TOTP_GET(verify, 6, 30))
|
||||
@ -131,24 +124,21 @@ func _ssh_conn(m *ice.Message, cb func(*ssh.Client), arg ...string) {
|
||||
return
|
||||
}))
|
||||
methods = append(methods, ssh.PublicKeysCallback(func() ([]ssh.Signer, error) {
|
||||
key, err := ssh.ParsePrivateKey([]byte(m.Cmdx(nfs.CAT, path.Join(kit.Env(cli.HOME), m.Option(PRIVATE)))))
|
||||
key, err := ssh.ParsePrivateKey([]byte(m.Cmdx(nfs.CAT, kit.HomePath(m.Option(PRIVATE)))))
|
||||
return []ssh.Signer{key}, err
|
||||
}))
|
||||
methods = append(methods, ssh.PasswordCallback(func() (string, error) {
|
||||
return m.Option(aaa.PASSWORD), nil
|
||||
}))
|
||||
|
||||
m.OptionCB(tcp.CLIENT, func(c net.Conn) {
|
||||
m.Cmdy(tcp.CLIENT, tcp.DIAL, mdb.TYPE, SSH, mdb.NAME, m.Option(tcp.HOST), m.OptionSimple(tcp.HOST, tcp.PORT), arg, func(c net.Conn) {
|
||||
conn, chans, reqs, err := ssh.NewClientConn(c, m.Option(tcp.HOST)+":"+m.Option(tcp.PORT), &ssh.ClientConfig{
|
||||
User: m.Option(aaa.USERNAME), Auth: methods, BannerCallback: func(message string) error { return nil },
|
||||
HostKeyCallback: func(hostname string, remote net.Addr, key ssh.PublicKey) error { return nil },
|
||||
})
|
||||
|
||||
m.Assert(err)
|
||||
cb(ssh.NewClient(conn, chans, reqs))
|
||||
})
|
||||
m.Cmdy(tcp.CLIENT, tcp.DIAL, mdb.TYPE, SSH, mdb.NAME, m.Option(tcp.HOST),
|
||||
tcp.PORT, m.Option(tcp.PORT), tcp.HOST, m.Option(tcp.HOST), arg)
|
||||
}
|
||||
|
||||
const SSH = "ssh"
|
||||
@ -160,52 +150,36 @@ func init() {
|
||||
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) {
|
||||
aaa.UserRoot(m)
|
||||
_ssh_open(nfs.OptionLoad(m, m.Option("authfile")), arg...)
|
||||
m.Echo("exit %v@%v:%v\n", m.Option(aaa.USERNAME), m.Option(tcp.HOST), m.Option(tcp.PORT))
|
||||
m.Echo("exit %s@%s:%s\n", m.Option(aaa.USERNAME), m.Option(tcp.HOST), m.Option(tcp.PORT))
|
||||
}},
|
||||
tcp.DIAL: {Name: "dial name=shylinux username=shy host=shylinux.com port=22 private=.ssh/id_rsa", Help: "添加", Hand: func(m *ice.Message, arg ...string) {
|
||||
tcp.DIAL: {Name: "dial name=shylinux host=shylinux.com port=22 username=shy private=.ssh/id_rsa", Help: "添加", Hand: func(m *ice.Message, arg ...string) {
|
||||
m.Go(func() {
|
||||
_ssh_conn(m, func(client *ssh.Client) {
|
||||
mdb.Rich(m, CONNECT, "", kit.Dict(
|
||||
mdb.NAME, m.Option(mdb.NAME),
|
||||
aaa.USERNAME, m.Option(aaa.USERNAME),
|
||||
tcp.HOST, m.Option(tcp.HOST), tcp.PORT, m.Option(tcp.PORT),
|
||||
mdb.STATUS, tcp.OPEN, CONNECT, client,
|
||||
))
|
||||
m.Cmd(CONNECT, SESSION, mdb.NAME, m.Option(mdb.NAME))
|
||||
mdb.HashCreate(m.Spawn(), m.OptionSimple(mdb.NAME, tcp.HOST, tcp.PORT, aaa.USERNAME), mdb.STATUS, tcp.OPEN, kit.Dict(mdb.TARGET, client))
|
||||
m.Cmd("", SESSION, m.OptionSimple(mdb.NAME))
|
||||
}, arg...)
|
||||
})
|
||||
m.ProcessRefresh3s()
|
||||
m.Sleep300ms()
|
||||
}},
|
||||
SESSION: {Name: "session name", Help: "会话", Hand: func(m *ice.Message, arg ...string) {
|
||||
var client *ssh.Client
|
||||
mdb.Richs(m, CONNECT, "", m.Option(mdb.NAME), func(key string, value ice.Map) {
|
||||
client, _ = value[CONNECT].(*ssh.Client)
|
||||
})
|
||||
|
||||
h := mdb.Rich(m, SESSION, "", kit.Data(mdb.NAME, m.Option(mdb.NAME), mdb.STATUS, tcp.OPEN, CONNECT, m.Option(mdb.NAME)))
|
||||
if session, e := _ssh_session(m, h, client); m.Assert(e) {
|
||||
session.Shell()
|
||||
session.Wait()
|
||||
SESSION: {Name: "session", Help: "会话", Hand: func(m *ice.Message, arg ...string) {
|
||||
if c, e := _ssh_session(m, mdb.HashTarget(m, m.Option(mdb.NAME), nil).(*ssh.Client)); m.Assert(e) {
|
||||
defer c.Wait()
|
||||
c.Shell()
|
||||
}
|
||||
m.Echo(h)
|
||||
}},
|
||||
"command": {Name: "command cmd=pwd", Help: "命令", Hand: func(m *ice.Message, arg ...string) {
|
||||
mdb.Richs(m, CONNECT, "", m.Option(mdb.NAME), func(key string, value ice.Map) {
|
||||
if client, ok := value[CONNECT].(*ssh.Client); ok {
|
||||
if session, e := client.NewSession(); m.Assert(e) {
|
||||
defer session.Close()
|
||||
if b, e := session.CombinedOutput(m.Option("cmd")); m.Assert(e) {
|
||||
m.Echo(string(b))
|
||||
}
|
||||
}
|
||||
ctx.COMMAND: {Name: "command cmd=pwd", Help: "命令", Hand: func(m *ice.Message, arg ...string) {
|
||||
client := mdb.HashTarget(m, m.Option(mdb.NAME), nil).(*ssh.Client)
|
||||
if s, e := client.NewSession(); m.Assert(e) {
|
||||
defer s.Close()
|
||||
if b, e := s.CombinedOutput(m.Option(ice.CMD)); m.Assert(e) {
|
||||
m.Echo(string(b))
|
||||
}
|
||||
})
|
||||
}
|
||||
}},
|
||||
}, mdb.HashStatusAction(mdb.SHORT, "name", mdb.FIELD, "time,name,status,username,host,port")), Hand: func(m *ice.Message, arg ...string) {
|
||||
mdb.HashSelect(m, arg...).Tables(func(value ice.Maps) {
|
||||
if mdb.HashSelect(m, arg...).Tables(func(value ice.Maps) {
|
||||
m.PushButton(kit.Select("", "command,session", value[mdb.STATUS] == tcp.OPEN), mdb.REMOVE)
|
||||
})
|
||||
if len(arg) == 0 {
|
||||
}); len(arg) == 0 {
|
||||
m.Action(tcp.DIAL)
|
||||
}
|
||||
}},
|
||||
|
@ -6,7 +6,6 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
"path"
|
||||
"strings"
|
||||
|
||||
"golang.org/x/crypto/ssh"
|
||||
@ -17,6 +16,7 @@ import (
|
||||
"shylinux.com/x/icebergs/base/nfs"
|
||||
psh "shylinux.com/x/icebergs/base/ssh"
|
||||
"shylinux.com/x/icebergs/base/tcp"
|
||||
"shylinux.com/x/icebergs/base/web"
|
||||
kit "shylinux.com/x/toolkits"
|
||||
)
|
||||
|
||||
@ -27,11 +27,11 @@ func _ssh_config(m *ice.Message, h string) *ssh.ServerConfig {
|
||||
config := &ssh.ServerConfig{
|
||||
PublicKeyCallback: func(conn ssh.ConnMetadata, key ssh.PublicKey) (*ssh.Permissions, error) {
|
||||
meta, err := _ssh_meta(conn), errors.New(ice.ErrNotRight)
|
||||
if tcp.IsLocalHost(m, strings.Split(conn.RemoteAddr().String(), ":")[0]) {
|
||||
if tcp.IsLocalHost(m, strings.Split(conn.RemoteAddr().String(), ice.DF)[0]) {
|
||||
m.Logs(ice.LOG_AUTH, tcp.HOSTPORT, conn.RemoteAddr(), aaa.USERNAME, conn.User())
|
||||
err = nil // 本机用户
|
||||
} else {
|
||||
m.Cmd(mdb.SELECT, SERVICE, kit.Keys(mdb.HASH, h), mdb.LIST, func(value ice.Maps) {
|
||||
mdb.ZoneSelectCB(m, h, func(value ice.Maps) {
|
||||
if !strings.HasPrefix(value[mdb.NAME], conn.User()+"@") {
|
||||
return
|
||||
}
|
||||
@ -57,14 +57,13 @@ func _ssh_config(m *ice.Message, h string) *ssh.ServerConfig {
|
||||
}
|
||||
return &ssh.Permissions{Extensions: meta}, err
|
||||
},
|
||||
|
||||
BannerCallback: func(conn ssh.ConnMetadata) string {
|
||||
m.Logs(ice.LOG_AUTH, tcp.HOSTPORT, conn.RemoteAddr(), aaa.USERNAME, conn.User())
|
||||
return m.Conf(SERVICE, kit.Keym(WELCOME))
|
||||
return m.Config(WELCOME)
|
||||
},
|
||||
}
|
||||
|
||||
if key, err := ssh.ParsePrivateKey([]byte(m.Cmdx(nfs.CAT, path.Join(kit.Env(cli.HOME), m.Option(PRIVATE))))); m.Assert(err) {
|
||||
if key, err := ssh.ParsePrivateKey([]byte(m.Cmdx(nfs.CAT, kit.HomePath(m.Option(PRIVATE))))); m.Assert(err) {
|
||||
config.AddHostKey(key)
|
||||
}
|
||||
return config
|
||||
@ -100,30 +99,30 @@ const SERVICE = "service"
|
||||
func init() {
|
||||
psh.Index.Merge(&ice.Context{Configs: ice.Configs{
|
||||
SERVICE: {Name: SERVICE, Help: "服务", Value: kit.Data(
|
||||
WELCOME, "\r\nwelcome to context world\r\n", GOODBYE, "\r\ngoodbye of context world\r\n",
|
||||
mdb.SHORT, tcp.PORT, mdb.FIELD, "time,port,status,private,authkey,count",
|
||||
WELCOME, "\r\nwelcome to contexts world\r\n", GOODBYE, "\r\ngoodbye of contexts world\r\n",
|
||||
)},
|
||||
}, Commands: ice.Commands{
|
||||
SERVICE: {Name: "service port id auto listen prunes", Help: "服务", Actions: ice.MergeActions(ice.Actions{
|
||||
ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) {
|
||||
mdb.Richs(m, SERVICE, "", mdb.FOREACH, func(key string, value ice.Map) {
|
||||
if value = kit.GetMeta(value); kit.Value(value, mdb.STATUS) == tcp.OPEN {
|
||||
mdb.HashSelect(m).Tables(func(value ice.Maps) {
|
||||
if value[mdb.STATUS] == tcp.OPEN {
|
||||
m.Cmd(SERVICE, tcp.LISTEN, tcp.PORT, value[tcp.PORT], value)
|
||||
}
|
||||
})
|
||||
}},
|
||||
tcp.LISTEN: {Name: "listen port=9030 private=.ssh/id_rsa authkey=.ssh/authorized_keys", Help: "添加", Hand: func(m *ice.Message, arg ...string) {
|
||||
if mdb.Richs(m, SERVICE, "", m.Option(tcp.PORT), func(key string, value ice.Map) {
|
||||
kit.Value(value, kit.Keym(mdb.STATUS), tcp.OPEN)
|
||||
}) == nil {
|
||||
m.Cmd(mdb.INSERT, SERVICE, "", mdb.HASH, tcp.PORT, m.Option(tcp.PORT),
|
||||
PRIVATE, m.Option(PRIVATE), AUTHKEY, m.Option(AUTHKEY), mdb.STATUS, tcp.OPEN, arg)
|
||||
m.Cmd(SERVICE, mdb.IMPORT, AUTHKEY, m.Option(AUTHKEY))
|
||||
if mdb.HashSelect(m, m.Option(tcp.PORT)).Length() > 0 {
|
||||
mdb.HashModify(m, m.Option(tcp.PORT), mdb.STATUS, tcp.OPEN)
|
||||
} else {
|
||||
mdb.HashCreate(m, mdb.STATUS, tcp.OPEN, arg)
|
||||
m.Cmd("", nfs.LOAD, m.OptionSimple(AUTHKEY))
|
||||
}
|
||||
|
||||
m.OptionCB(tcp.SERVER, func(c net.Conn) { m.Go(func() { _ssh_accept(m, kit.Hashs(m.Option(tcp.PORT)), c) }) })
|
||||
m.Go(func() {
|
||||
m.Cmdy(tcp.SERVER, tcp.LISTEN, mdb.TYPE, SSH, mdb.NAME, tcp.PORT, tcp.PORT, m.Option(tcp.PORT))
|
||||
m.Cmdy(tcp.SERVER, tcp.LISTEN, mdb.TYPE, SSH, mdb.NAME, tcp.PORT, m.OptionSimple(tcp.PORT), func(c net.Conn) {
|
||||
m.Go(func() { _ssh_accept(m, kit.Hashs(m.Option(tcp.PORT)), c) })
|
||||
})
|
||||
})
|
||||
}},
|
||||
|
||||
@ -133,36 +132,29 @@ func init() {
|
||||
mdb.TYPE, ls[0], mdb.NAME, ls[len(ls)-1], mdb.TEXT, strings.Join(ls[1:len(ls)-1], "+"))
|
||||
}
|
||||
}},
|
||||
mdb.EXPORT: {Name: "export authkey=.ssh/authorized_keys", Help: "导出", Hand: func(m *ice.Message, arg ...string) {
|
||||
nfs.LOAD: {Name: "load authkey=.ssh/authorized_keys", Help: "加载", Hand: func(m *ice.Message, arg ...string) {
|
||||
m.Cmd(nfs.CAT, kit.HomePath(m.Option(AUTHKEY)), func(pub string) {
|
||||
m.Cmd(SERVICE, mdb.INSERT, mdb.TEXT, pub)
|
||||
})
|
||||
}},
|
||||
nfs.SAVE: {Name: "save authkey=.ssh/authorized_keys", Help: "保存", Hand: func(m *ice.Message, arg ...string) {
|
||||
list := []string{}
|
||||
m.Cmd(mdb.SELECT, SERVICE, kit.Keys(mdb.HASH, kit.Hashs(m.Option(tcp.PORT))), mdb.LIST, func(value ice.Maps) {
|
||||
mdb.ZoneSelectCB(m, m.Option(tcp.PORT), func(value ice.Maps) {
|
||||
list = append(list, fmt.Sprintf("%s %s %s", value[mdb.TYPE], value[mdb.TEXT], value[mdb.NAME]))
|
||||
})
|
||||
|
||||
if len(list) > 0 {
|
||||
m.Cmdy(nfs.SAVE, path.Join(kit.Env(cli.HOME), m.Option(AUTHKEY)), strings.Join(list, ice.NL)+ice.NL)
|
||||
m.Cmdy(nfs.SAVE, kit.HomePath(m.Option(AUTHKEY)), strings.Join(list, ice.NL)+ice.NL)
|
||||
}
|
||||
}},
|
||||
mdb.IMPORT: {Name: "import authkey=.ssh/authorized_keys", Help: "导入", Hand: func(m *ice.Message, arg ...string) {
|
||||
p := path.Join(kit.Env(cli.HOME), m.Option(AUTHKEY))
|
||||
for _, pub := range strings.Split(strings.TrimSpace(m.Cmdx(nfs.CAT, p)), ice.NL) {
|
||||
m.Cmd(SERVICE, mdb.INSERT, mdb.TEXT, pub)
|
||||
}
|
||||
m.Echo(p)
|
||||
}},
|
||||
aaa.INVITE: {Name: "invite", Help: "邀请", Hand: func(m *ice.Message, arg ...string) {
|
||||
u := kit.ParseURL(m.Option(ice.MSG_USERWEB))
|
||||
m.Option(cli.HOSTNAME, strings.Split(u.Host, ":")[0])
|
||||
m.ProcessInner()
|
||||
|
||||
m.Option(cli.HOSTNAME, web.OptionUserWeb(m).Hostname())
|
||||
if buf, err := kit.Render(`ssh -p {{.Option "port"}} {{.Option "user.name"}}@{{.Option "hostname"}}`, m); err == nil {
|
||||
m.EchoScript(string(buf))
|
||||
}
|
||||
}},
|
||||
}, mdb.HashStatusAction()), Hand: func(m *ice.Message, arg ...string) {
|
||||
if len(arg) == 0 { // 服务列表
|
||||
mdb.HashSelect(m, arg...)
|
||||
m.PushAction(mdb.IMPORT, mdb.INSERT, mdb.EXPORT, aaa.INVITE)
|
||||
mdb.HashSelect(m, arg...).PushAction(aaa.INVITE, mdb.INSERT, nfs.LOAD, nfs.SAVE)
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -7,8 +7,9 @@ import (
|
||||
"syscall"
|
||||
"unsafe"
|
||||
|
||||
pty "shylinux.com/x/creackpty"
|
||||
"golang.org/x/crypto/ssh"
|
||||
pty "shylinux.com/x/creackpty"
|
||||
|
||||
ice "shylinux.com/x/icebergs"
|
||||
"shylinux.com/x/icebergs/base/cli"
|
||||
"shylinux.com/x/icebergs/base/mdb"
|
||||
@ -33,7 +34,7 @@ func _ssh_handle(m *ice.Message, meta ice.Maps, c net.Conn, channel ssh.Channel,
|
||||
m.Logs(CHANNEL, tcp.HOSTPORT, c.RemoteAddr(), "->", c.LocalAddr())
|
||||
defer m.Logs("dischan", tcp.HOSTPORT, c.RemoteAddr(), "->", c.LocalAddr())
|
||||
|
||||
shell := kit.Select("bash", kit.Env("SHELL"))
|
||||
shell := kit.Select("bash", kit.Env(cli.SHELL))
|
||||
list := []string{cli.PATH + "=" + kit.Env(cli.PATH)}
|
||||
|
||||
pty, tty, err := pty.Open()
|
||||
|
@ -4,6 +4,7 @@ import (
|
||||
"io"
|
||||
|
||||
"golang.org/x/crypto/ssh"
|
||||
|
||||
ice "shylinux.com/x/icebergs"
|
||||
"shylinux.com/x/icebergs/base/ctx"
|
||||
"shylinux.com/x/icebergs/base/mdb"
|
||||
@ -12,35 +13,27 @@ import (
|
||||
kit "shylinux.com/x/toolkits"
|
||||
)
|
||||
|
||||
func _ssh_session(m *ice.Message, h string, client *ssh.Client) (*ssh.Session, error) {
|
||||
session, e := client.NewSession()
|
||||
func _ssh_session(m *ice.Message, client *ssh.Client) (*ssh.Session, error) {
|
||||
s, e := client.NewSession()
|
||||
m.Assert(e)
|
||||
out, e := s.StdoutPipe()
|
||||
m.Assert(e)
|
||||
in, e := s.StdinPipe()
|
||||
m.Assert(e)
|
||||
|
||||
out, e := session.StdoutPipe()
|
||||
m.Assert(e)
|
||||
|
||||
in, e := session.StdinPipe()
|
||||
m.Assert(e)
|
||||
h := m.Cmdx(SESSION, mdb.CREATE, mdb.STATUS, tcp.OPEN, CONNECT, m.Option(mdb.NAME), kit.Dict(mdb.TARGET, in))
|
||||
|
||||
m.Go(func() {
|
||||
buf := make([]byte, ice.MOD_BUFS)
|
||||
for {
|
||||
n, e := out.Read(buf)
|
||||
if e != nil {
|
||||
if n, e := out.Read(buf); e != nil {
|
||||
break
|
||||
} else {
|
||||
m.Cmd(SESSION, mdb.INSERT, mdb.HASH, h, mdb.TYPE, RES, mdb.TEXT, string(buf[:n]))
|
||||
}
|
||||
|
||||
mdb.Grow(m, SESSION, kit.Keys(mdb.HASH, h), kit.Dict(
|
||||
mdb.TYPE, RES, mdb.TEXT, string(buf[:n]),
|
||||
))
|
||||
}
|
||||
})
|
||||
|
||||
mdb.Richs(m, SESSION, "", h, func(key string, value ice.Map) {
|
||||
kit.Value(value, kit.Keym(OUTPUT), out, kit.Keym(INPUT), in)
|
||||
})
|
||||
|
||||
return session, nil
|
||||
return s, nil
|
||||
}
|
||||
|
||||
const (
|
||||
@ -59,20 +52,17 @@ const SESSION = "session"
|
||||
|
||||
func init() {
|
||||
psh.Index.MergeCommands(ice.Commands{
|
||||
SESSION: {Name: "session name id auto", Help: "会话", Actions: ice.MergeActions(ice.Actions{
|
||||
SESSION: {Name: "session hash id auto", Help: "会话", Actions: ice.MergeActions(ice.Actions{
|
||||
mdb.REPEAT: {Name: "repeat", Help: "执行", Hand: func(m *ice.Message, arg ...string) {
|
||||
m.Cmdy(SESSION, ctx.ACTION, ctx.COMMAND, CMD, m.Option(mdb.TEXT))
|
||||
m.Cmdy("", ctx.COMMAND, CMD, m.Option(mdb.TEXT))
|
||||
}},
|
||||
ctx.COMMAND: {Name: "command cmd=pwd", Help: "命令", Hand: func(m *ice.Message, arg ...string) {
|
||||
mdb.Richs(m, SESSION, "", m.Option(mdb.NAME), func(key string, value ice.Map) {
|
||||
if w, ok := kit.Value(value, kit.Keym(INPUT)).(io.Writer); ok {
|
||||
mdb.Grow(m, SESSION, kit.Keys(mdb.HASH, key), kit.Dict(mdb.TYPE, CMD, mdb.TEXT, m.Option(CMD)))
|
||||
w.Write([]byte(m.Option(CMD) + ice.NL))
|
||||
}
|
||||
})
|
||||
m.ProcessRefresh300ms()
|
||||
m.Cmd("", mdb.INSERT, m.OptionSimple(mdb.HASH), mdb.TYPE, CMD, mdb.TEXT, m.Option(CMD))
|
||||
w := mdb.HashTarget(m, m.Option(mdb.HASH), nil).(io.Writer)
|
||||
w.Write([]byte(m.Option(CMD) + ice.NL))
|
||||
m.Sleep300ms()
|
||||
}},
|
||||
}, mdb.ZoneAction(mdb.SHORT, "name", mdb.FIELD, "time,name,status,count,connect")), Hand: func(m *ice.Message, arg ...string) {
|
||||
}, mdb.ZoneAction(mdb.FIELD, "time,hash,count,status,connect")), Hand: func(m *ice.Message, arg ...string) {
|
||||
if len(arg) == 0 {
|
||||
mdb.HashSelect(m, arg...).Tables(func(value ice.Maps) {
|
||||
m.PushButton(kit.Select("", ctx.COMMAND, value[mdb.STATUS] == tcp.OPEN), mdb.REMOVE)
|
||||
|
@ -6,7 +6,7 @@ refer `
|
||||
`
|
||||
|
||||
field "连接" ssh.connect
|
||||
field "通道" ssh.channel
|
||||
field "会话" ssh.session
|
||||
field "服务" ssh.service
|
||||
field "通道" ssh.channel
|
||||
|
||||
|
@ -8,8 +8,8 @@ import (
|
||||
)
|
||||
|
||||
type WebView struct {
|
||||
Source string
|
||||
WebView webview.WebView
|
||||
webview.WebView
|
||||
Source string
|
||||
}
|
||||
|
||||
func (w WebView) Menu() bool {
|
||||
@ -20,31 +20,29 @@ func (w WebView) Menu() bool {
|
||||
w.WebView.Bind(ls[0], func() { w.navigate(ls[1]) })
|
||||
}
|
||||
})
|
||||
|
||||
if len(list) == 0 {
|
||||
return false
|
||||
}
|
||||
|
||||
w.WebView.SetTitle("contexts")
|
||||
w.WebView.SetTitle(ice.CONTEXTS)
|
||||
w.WebView.SetSize(200, 60*len(list), webview.HintNone)
|
||||
w.WebView.Navigate(kit.Format(`data:text/html,
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<style>button { font-size:24px; font-family:monospace; margin:10px; width:-webkit-fill-available; display:block; clear:both; }</style>
|
||||
</head>
|
||||
|
||||
<body>%s</body>
|
||||
<script>
|
||||
document.body.onkeydown = function(event) {
|
||||
if (event.metaKey) {
|
||||
switch (event.key) {
|
||||
case "q": window.terminate(); break
|
||||
document.body.onkeydown = function(event) {
|
||||
if (event.metaKey) {
|
||||
switch (event.key) {
|
||||
case "q": window.terminate(); break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</html>`, kit.Join(list, ice.NL)))
|
||||
</head>
|
||||
<body>%s</body>
|
||||
</html>`, kit.Join(list, ice.NL)))
|
||||
return true
|
||||
}
|
||||
func (w WebView) Title(text string) { w.WebView.SetTitle(text) }
|
||||
|
Loading…
x
Reference in New Issue
Block a user