mirror of
https://shylinux.com/x/icebergs
synced 2025-04-26 01:24:05 +08:00
opt ssh
This commit is contained in:
parent
545ec26ea8
commit
f9302ca410
@ -8,22 +8,21 @@ import (
|
||||
|
||||
ice "github.com/shylinux/icebergs"
|
||||
"github.com/shylinux/icebergs/base/aaa"
|
||||
"github.com/shylinux/icebergs/base/ctx"
|
||||
"github.com/shylinux/icebergs/base/mdb"
|
||||
"github.com/shylinux/icebergs/base/tcp"
|
||||
kit "github.com/shylinux/toolkits"
|
||||
"golang.org/x/crypto/ssh"
|
||||
)
|
||||
|
||||
type Winsize struct{ Height, Width, x, y uint16 }
|
||||
|
||||
func _ssh_exec(m *ice.Message, cmd string, arg []string, env []string, tty io.ReadWriter, done func()) {
|
||||
func _ssh_exec(m *ice.Message, cmd string, arg []string, env []string, input io.Reader, output io.Writer, done func()) {
|
||||
m.Log_IMPORT(CMD, cmd, ARG, arg, ENV, env)
|
||||
c := exec.Command(cmd, arg...)
|
||||
// c.Env = env
|
||||
|
||||
c.Stdin = tty
|
||||
c.Stdout = tty
|
||||
c.Stderr = tty
|
||||
c.Stdin = input
|
||||
c.Stdout = output
|
||||
c.Stderr = output
|
||||
|
||||
m.Assert(c.Start())
|
||||
|
||||
@ -41,7 +40,7 @@ func _ssh_watch(m *ice.Message, meta map[string]string, h string, input io.Reade
|
||||
bio := io.TeeReader(input, w)
|
||||
m.Go(func() { io.Copy(output, r) })
|
||||
|
||||
i, buf := 0, make([]byte, 4096)
|
||||
i, buf := 0, make([]byte, ice.MOD_BUFS)
|
||||
m.Go(func() {
|
||||
for {
|
||||
n, e := bio.Read(buf[i:])
|
||||
@ -72,7 +71,7 @@ func init() {
|
||||
CHANNEL: {Name: "channel", Help: "通道", Value: kit.Data()},
|
||||
},
|
||||
Commands: map[string]*ice.Command{
|
||||
CHANNEL: {Name: "channel hash id auto prunes", Help: "通道", Action: map[string]*ice.Action{
|
||||
CHANNEL: {Name: "channel 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, CHANNEL, "", mdb.HASH, kit.MDB_HASH, m.Option(kit.MDB_HASH))
|
||||
}},
|
||||
@ -81,12 +80,24 @@ func init() {
|
||||
m.Cmdy(mdb.PRUNES, SERVICE, "", mdb.HASH, kit.MDB_STATUS, tcp.ERROR)
|
||||
m.Cmdy(mdb.PRUNES, CHANNEL, "", mdb.HASH, kit.MDB_STATUS, tcp.CLOSE)
|
||||
}},
|
||||
ctx.COMMAND: {Name: "command cmd=pwd", Help: "命令", Hand: func(m *ice.Message, arg ...string) {
|
||||
m.Cmdy(mdb.INSERT, CHANNEL, kit.Keys(kit.MDB_HASH, m.Option(kit.MDB_HASH)), mdb.LIST, kit.MDB_TYPE, CMD, kit.MDB_TEXT, m.Option(CMD))
|
||||
m.Richs(CHANNEL, "", m.Option(kit.MDB_HASH), func(key string, value map[string]interface{}) {
|
||||
if w, ok := kit.Value(value, kit.Keym(INPUT)).(io.Writer); ok {
|
||||
w.Write([]byte(m.Option(CMD) + "\n"))
|
||||
}
|
||||
})
|
||||
m.ProcessRefresh("300ms")
|
||||
}},
|
||||
"repeat": {Name: "repeat", Help: "执行", Hand: func(m *ice.Message, arg ...string) {
|
||||
m.Cmdy(CHANNEL, kit.MDB_ACTION, ctx.COMMAND, CMD, m.Option("text"))
|
||||
}},
|
||||
}, Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
|
||||
if len(arg) == 0 { // 通道列表
|
||||
m.Fields(len(arg) == 0, "time,hash,status,username,hostport,tty,count")
|
||||
if m.Cmdy(mdb.SELECT, CHANNEL, "", mdb.HASH); len(arg) == 0 {
|
||||
m.Table(func(index int, value map[string]string, head []string) {
|
||||
m.PushButton(kit.Select("", mdb.REMOVE, value[kit.MDB_STATUS] == tcp.CLOSE))
|
||||
m.PushButton(kit.Select("", ctx.COMMAND, value[kit.MDB_STATUS] == tcp.OPEN), mdb.REMOVE)
|
||||
})
|
||||
}
|
||||
return
|
||||
@ -95,6 +106,7 @@ func init() {
|
||||
// 通道命令
|
||||
m.Fields(len(arg) == 1, "time,id,type,text")
|
||||
m.Cmdy(mdb.SELECT, CHANNEL, kit.Keys(kit.MDB_HASH, arg[0]), mdb.LIST, kit.MDB_ID, arg[1:])
|
||||
m.PushAction("repeat")
|
||||
}},
|
||||
},
|
||||
})
|
||||
|
@ -1,7 +1,6 @@
|
||||
package ssh
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
@ -22,16 +21,6 @@ import (
|
||||
)
|
||||
|
||||
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 interface{}) { m.Option(key, kit.Simple(value)) })
|
||||
}
|
||||
|
||||
_ssh_dial(m, func(c net.Conn) {
|
||||
// 保存界面
|
||||
fd := int(os.Stdin.Fd())
|
||||
@ -44,13 +33,12 @@ func _ssh_open(m *ice.Message, arg ...string) {
|
||||
c.Write([]byte(fmt.Sprintf("height:%d,width:%d\n", h, w)))
|
||||
|
||||
// 初始命令
|
||||
for _, item := range kit.Simple(m.Optionv("list")) {
|
||||
for _, item := range kit.Simple(m.Optionv(kit.MDB_LIST)) {
|
||||
m.Sleep("500ms")
|
||||
c.Write([]byte(item + "\n"))
|
||||
}
|
||||
|
||||
m.Go(func() { io.Copy(c, os.Stdin) })
|
||||
|
||||
io.Copy(os.Stdout, c)
|
||||
}, arg...)
|
||||
}
|
||||
@ -64,67 +52,62 @@ func _ssh_dial(m *ice.Message, cb func(net.Conn), arg ...string) {
|
||||
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()
|
||||
_ssh_conn(m, func(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()
|
||||
if e != nil {
|
||||
break
|
||||
}
|
||||
|
||||
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() {
|
||||
for {
|
||||
c, e := l.Accept()
|
||||
if e != nil {
|
||||
break
|
||||
}
|
||||
|
||||
m.Go(func() {
|
||||
defer c.Close()
|
||||
|
||||
session, e := client.NewSession()
|
||||
if e != nil {
|
||||
return
|
||||
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)
|
||||
}
|
||||
|
||||
session.Stdin = c
|
||||
session.Stdout = c
|
||||
session.Stderr = c
|
||||
m.Go(func() {
|
||||
defer c.Close()
|
||||
|
||||
session.RequestPty(os.Getenv("TERM"), h, w, ssh.TerminalModes{
|
||||
ssh.ECHO: 1,
|
||||
ssh.TTY_OP_ISPEED: 14400,
|
||||
ssh.TTY_OP_OSPEED: 14400,
|
||||
session, e := client.NewSession()
|
||||
if e != nil {
|
||||
return
|
||||
}
|
||||
|
||||
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()
|
||||
})
|
||||
|
||||
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))
|
||||
}(c)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
if c, e := net.Dial("unix", p); e == nil {
|
||||
cb(c) // 会话连接
|
||||
}
|
||||
})
|
||||
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)
|
||||
}, arg...)
|
||||
}
|
||||
func _ssh_conn(m *ice.Message, conn net.Conn, username, hostport string) *ssh.Client {
|
||||
func _ssh_conn(m *ice.Message, cb func(*ssh.Client), arg ...string) {
|
||||
methods := []ssh.AuthMethod{}
|
||||
methods = append(methods, ssh.KeyboardInteractive(func(user, instruction string, questions []string, echos []bool) (res []string, err error) {
|
||||
for _, q := range questions {
|
||||
@ -146,22 +129,25 @@ func _ssh_conn(m *ice.Message, conn net.Conn, username, hostport string) *ssh.Cl
|
||||
}
|
||||
return
|
||||
}))
|
||||
|
||||
methods = append(methods, ssh.PublicKeysCallback(func() ([]ssh.Signer, error) {
|
||||
key, err := ssh.ParsePrivateKey([]byte(m.Cmdx(nfs.CAT, path.Join(os.Getenv(cli.HOME), m.Option("private")))))
|
||||
key, err := ssh.ParsePrivateKey([]byte(m.Cmdx(nfs.CAT, path.Join(os.Getenv(cli.HOME), m.Option(PRIVATE)))))
|
||||
return []ssh.Signer{key}, err
|
||||
}))
|
||||
methods = append(methods, ssh.PasswordCallback(func() (string, error) {
|
||||
return m.Option(aaa.PASSWORD), nil
|
||||
}))
|
||||
|
||||
c, chans, reqs, err := ssh.NewClientConn(conn, hostport, &ssh.ClientConfig{
|
||||
User: username, Auth: methods, BannerCallback: func(message string) error { return nil },
|
||||
HostKeyCallback: func(hostname string, remote net.Addr, key ssh.PublicKey) error { return nil },
|
||||
})
|
||||
m.Option(kit.Keycb(tcp.DIAL), 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)
|
||||
return ssh.NewClient(c, chans, reqs)
|
||||
m.Assert(err)
|
||||
cb(ssh.NewClient(conn, chans, reqs))
|
||||
})
|
||||
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)
|
||||
}
|
||||
|
||||
const CONNECT = "connect"
|
||||
@ -175,59 +161,61 @@ func init() {
|
||||
ice.CTX_INIT: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
|
||||
m.Richs(CONNECT, "", kit.MDB_FOREACH, func(key string, value map[string]interface{}) {
|
||||
if value = kit.GetMeta(value); kit.Value(value, kit.MDB_STATUS) == tcp.OPEN {
|
||||
m.Cmd(CONNECT, tcp.DIAL, aaa.USERNAME, value[aaa.USERNAME], value)
|
||||
m.Cmd(CONNECT, tcp.DIAL, aaa.USERNAME, value[aaa.USERNAME], kit.MDB_HASH, key, value)
|
||||
}
|
||||
})
|
||||
}},
|
||||
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...)
|
||||
_ssh_open(m.OptionLoad(m.Option("authfile")), arg...)
|
||||
m.Echo("exit %v:%v\n", m.Option(tcp.HOST), m.Option(tcp.PORT))
|
||||
}},
|
||||
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)),
|
||||
kit.Select("shylinux.com", m.Option(tcp.HOST))+":"+kit.Select("22", m.Option(tcp.PORT)),
|
||||
)
|
||||
|
||||
h := m.Rich(CONNECT, "", kit.Dict(
|
||||
aaa.USERNAME, m.Option(aaa.USERNAME),
|
||||
tcp.HOST, m.Option(tcp.HOST), tcp.PORT, m.Option(tcp.PORT),
|
||||
kit.MDB_STATUS, tcp.OPEN, CONNECT, client,
|
||||
))
|
||||
m.Cmd(CONNECT, SESSION, kit.MDB_HASH, h)
|
||||
m.Echo(h)
|
||||
m.Go(func() {
|
||||
_ssh_conn(m, func(client *ssh.Client) {
|
||||
h := m.Option(kit.MDB_HASH)
|
||||
if h == "" {
|
||||
h = m.Rich(CONNECT, "", kit.Dict(
|
||||
aaa.USERNAME, m.Option(aaa.USERNAME),
|
||||
tcp.HOST, m.Option(tcp.HOST), tcp.PORT, m.Option(tcp.PORT),
|
||||
kit.MDB_STATUS, tcp.OPEN, CONNECT, client,
|
||||
))
|
||||
} else {
|
||||
m.Conf(CONNECT, kit.Keys(kit.MDB_HASH, h, CONNECT), client)
|
||||
}
|
||||
m.Cmd(CONNECT, SESSION, kit.MDB_HASH, h)
|
||||
}, arg...)
|
||||
})
|
||||
|
||||
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))
|
||||
m.ProcessRefresh("300ms")
|
||||
}},
|
||||
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))
|
||||
}},
|
||||
mdb.PRUNES: {Name: "prunes", Help: "清理", Hand: func(m *ice.Message, arg ...string) {
|
||||
m.Option(mdb.FIELDS, "time,hash,status,username,host,port")
|
||||
m.Cmdy(mdb.PRUNES, CONNECT, "", mdb.HASH, kit.MDB_STATUS, tcp.ERROR)
|
||||
m.Cmdy(mdb.PRUNES, CONNECT, "", mdb.HASH, kit.MDB_STATUS, tcp.CLOSE)
|
||||
}},
|
||||
|
||||
SESSION: {Name: "session hash", Help: "会话", Hand: func(m *ice.Message, arg ...string) {
|
||||
var client *ssh.Client
|
||||
m.Richs(CONNECT, "", m.Option(kit.MDB_HASH), func(key string, value map[string]interface{}) {
|
||||
client, ok := value[CONNECT].(*ssh.Client)
|
||||
m.Assert(ok)
|
||||
|
||||
h := m.Rich(SESSION, "", kit.Data(kit.MDB_STATUS, tcp.OPEN, CONNECT, key))
|
||||
|
||||
if session, e := _ssh_session(m, h, client); m.Assert(e) {
|
||||
session.Shell()
|
||||
session.Wait()
|
||||
}
|
||||
client, _ = value[CONNECT].(*ssh.Client)
|
||||
})
|
||||
m.Debug("what %v", client)
|
||||
|
||||
h := m.Rich(SESSION, "", kit.Data(kit.MDB_STATUS, tcp.OPEN, CONNECT, m.Option(kit.MDB_HASH)))
|
||||
if session, e := _ssh_session(m, h, client); m.Assert(e) {
|
||||
session.Shell()
|
||||
session.Wait()
|
||||
}
|
||||
m.Echo(h)
|
||||
}},
|
||||
}, Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
|
||||
m.Fields(len(arg) == 0, "time,hash,status,username,host,port")
|
||||
if m.Cmdy(mdb.SELECT, CONNECT, "", mdb.HASH, kit.MDB_HASH, arg); len(arg) == 0 {
|
||||
m.Table(func(index int, value map[string]string, head []string) {
|
||||
m.PushButton(kit.Select("", mdb.REMOVE, value[kit.MDB_STATUS] == tcp.CLOSE))
|
||||
m.PushButton(kit.Select("", SESSION, value[kit.MDB_STATUS] == tcp.OPEN), mdb.REMOVE)
|
||||
})
|
||||
}
|
||||
}},
|
||||
|
@ -17,14 +17,21 @@ import (
|
||||
kit "github.com/shylinux/toolkits"
|
||||
)
|
||||
|
||||
func Render(msg *ice.Message, cmd string, args ...interface{}) {
|
||||
func Render(msg *ice.Message, cmd string, args ...interface{}) string {
|
||||
switch arg := kit.Simple(args...); cmd {
|
||||
case ice.RENDER_VOID:
|
||||
case ice.RENDER_RESULT:
|
||||
// 转换结果
|
||||
if len(arg) > 0 {
|
||||
msg.Resultv(arg)
|
||||
}
|
||||
fmt.Fprint(msg.O, msg.Result())
|
||||
res := msg.Result()
|
||||
|
||||
// 输出结果
|
||||
if fmt.Fprint(msg.O, res); !strings.HasSuffix(res, "\n") {
|
||||
fmt.Fprint(msg.O, "\n")
|
||||
}
|
||||
return res
|
||||
|
||||
default:
|
||||
// 转换结果
|
||||
@ -37,7 +44,9 @@ func Render(msg *ice.Message, cmd string, args ...interface{}) {
|
||||
if fmt.Fprint(msg.O, res); !strings.HasSuffix(res, "\n") {
|
||||
fmt.Fprint(msg.O, "\n")
|
||||
}
|
||||
return res
|
||||
}
|
||||
return ""
|
||||
}
|
||||
func Script(m *ice.Message, name string) io.Reader {
|
||||
if strings.Contains(m.Option(ice.MSG_SCRIPT), "/") {
|
||||
@ -92,6 +101,7 @@ type Frame struct {
|
||||
pipe io.Writer
|
||||
|
||||
count int
|
||||
last string
|
||||
ps1 []string
|
||||
ps2 []string
|
||||
|
||||
@ -223,7 +233,7 @@ func (f *Frame) parse(m *ice.Message, line string) string {
|
||||
|
||||
// 渲染引擎
|
||||
_args, _ := msg.Optionv(ice.MSG_ARGS).([]interface{})
|
||||
Render(msg, msg.Option(ice.MSG_OUTPUT), _args...)
|
||||
f.last = Render(msg, msg.Option(ice.MSG_OUTPUT), _args...)
|
||||
}
|
||||
return ""
|
||||
}
|
||||
@ -312,10 +322,16 @@ func (f *Frame) Start(m *ice.Message, arg ...string) bool {
|
||||
|
||||
// 解析脚本
|
||||
if f.count = 1; f.source == STDIO {
|
||||
f.count = kit.Int(m.Conf(SOURCE, kit.Keys("hash.stdio.meta.count"))) + 1
|
||||
m.Conf(SOURCE, kit.Keys(kit.MDB_HASH, STDIO, kit.MDB_META, kit.MDB_NAME), STDIO)
|
||||
m.Conf(SOURCE, kit.Keys(kit.MDB_HASH, STDIO, kit.MDB_META, kit.MDB_TIME), m.Time())
|
||||
|
||||
f.count = kit.Int(m.Conf(SOURCE, kit.Keys(kit.MDB_HASH, STDIO, kit.Keym(kit.MDB_COUNT)))) + 1
|
||||
f.scan(m, STDIO, "")
|
||||
} else {
|
||||
h := m.Cmdx(mdb.INSERT, SOURCE, "", mdb.HASH, kit.MDB_NAME, f.source)
|
||||
m.Conf(SOURCE, kit.Keys(kit.MDB_HASH, h, kit.Keym(kit.MDB_COUNT)), 0)
|
||||
m.Conf(SOURCE, kit.Keys(kit.MDB_HASH, h, kit.MDB_LIST), "")
|
||||
|
||||
f.scan(m, h, "")
|
||||
}
|
||||
return true
|
||||
@ -349,7 +365,12 @@ func init() {
|
||||
)},
|
||||
},
|
||||
Commands: map[string]*ice.Command{
|
||||
SOURCE: {Name: "source hash id limit offend auto", Help: "脚本解析", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
|
||||
SOURCE: {Name: "source hash id limit offend auto", Help: "脚本解析", Action: map[string]*ice.Action{
|
||||
"repeat": {Name: "repeat", Help: "执行", Hand: func(m *ice.Message, arg ...string) {
|
||||
m.Cmdy(SCREEN, m.Option("text"))
|
||||
m.ProcessInner()
|
||||
}},
|
||||
}, Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
|
||||
if len(arg) > 0 && kit.Ext(arg[0]) == "shy" { // 解析脚本
|
||||
m.Starts(strings.Replace(arg[0], ".", "_", -1), arg[0], arg[0:]...)
|
||||
return
|
||||
@ -371,6 +392,7 @@ func init() {
|
||||
// 命令列表
|
||||
m.Fields(len(arg) == 1 || arg[1] == "", "time,id,text")
|
||||
m.Cmdy(mdb.SELECT, SOURCE, kit.Keys(kit.MDB_HASH, arg[0]), mdb.LIST, kit.MDB_ID, arg[1:])
|
||||
m.PushAction("repeat")
|
||||
}},
|
||||
TARGET: {Name: "target name 执行:button", Help: "当前模块", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
|
||||
f := m.Target().Server().(*Frame)
|
||||
@ -396,7 +418,7 @@ func init() {
|
||||
fmt.Fprintf(f.pipe, line+"\n")
|
||||
m.Sleep("300ms")
|
||||
}
|
||||
m.Echo(arg[0])
|
||||
m.Echo(f.last)
|
||||
}},
|
||||
RETURN: {Name: "return", Help: "结束脚本", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
|
||||
switch cb := m.Optionv(kit.Keycb(RETURN)).(type) {
|
||||
|
@ -70,7 +70,7 @@ func _ssh_config(m *ice.Message, h string) *ssh.ServerConfig {
|
||||
return config
|
||||
}
|
||||
func _ssh_accept(m *ice.Message, h string, c net.Conn) {
|
||||
sc, chans, reqs, err := ssh.NewServerConn(c, _ssh_config(m, h))
|
||||
conn, chans, reqs, err := ssh.NewServerConn(c, _ssh_config(m, h))
|
||||
if m.Warn(err != nil, err) {
|
||||
return
|
||||
}
|
||||
@ -84,7 +84,7 @@ func _ssh_accept(m *ice.Message, h string, c net.Conn) {
|
||||
}
|
||||
|
||||
func(channel ssh.Channel, requests <-chan *ssh.Request) {
|
||||
m.Go(func() { _ssh_handle(m, sc.Permissions.Extensions, c, channel, requests) })
|
||||
m.Go(func() { _ssh_handle(m, conn.Permissions.Extensions, c, channel, requests) })
|
||||
}(channel, requests)
|
||||
}
|
||||
}
|
||||
|
@ -10,6 +10,8 @@ import (
|
||||
"golang.org/x/crypto/ssh"
|
||||
)
|
||||
|
||||
type Winsize struct{ Height, Width, x, y uint16 }
|
||||
|
||||
func _ssh_size(fd uintptr, b []byte) {
|
||||
w := binary.BigEndian.Uint32(b)
|
||||
h := binary.BigEndian.Uint32(b[4:])
|
||||
|
@ -17,6 +17,8 @@ import (
|
||||
"golang.org/x/crypto/ssh"
|
||||
)
|
||||
|
||||
type Winsize struct{ Height, Width, x, y uint16 }
|
||||
|
||||
func _ssh_size(fd uintptr, b []byte) {
|
||||
w := binary.BigEndian.Uint32(b)
|
||||
h := binary.BigEndian.Uint32(b[4:])
|
||||
@ -37,7 +39,7 @@ func _ssh_handle(m *ice.Message, meta map[string]string, c net.Conn, channel ssh
|
||||
}
|
||||
defer tty.Close()
|
||||
|
||||
h := m.Rich(CHANNEL, "", kit.Data(kit.MDB_STATUS, tcp.OPEN, TTY, tty.Name(), meta))
|
||||
h := m.Rich(CHANNEL, "", kit.Data(kit.MDB_STATUS, tcp.OPEN, TTY, tty.Name(), INPUT, pty, OUTPUT, tty, meta))
|
||||
meta[CHANNEL] = h
|
||||
|
||||
for request := range requests {
|
||||
@ -61,13 +63,13 @@ func _ssh_handle(m *ice.Message, meta map[string]string, c net.Conn, channel ssh
|
||||
list = append(list, env.Name+"="+env.Value)
|
||||
|
||||
case "exec":
|
||||
_ssh_exec(m, shell, []string{"-c", string(request.Payload[4 : request.Payload[3]+4])}, list, channel, func() {
|
||||
_ssh_exec(m, shell, []string{"-c", string(request.Payload[4 : request.Payload[3]+4])}, list, channel, channel, func() {
|
||||
channel.Close()
|
||||
})
|
||||
case "shell":
|
||||
m.Go(func() { io.Copy(channel, pty) })
|
||||
|
||||
_ssh_exec(m, shell, nil, list, tty, func() {
|
||||
_ssh_exec(m, shell, nil, list, tty, tty, func() {
|
||||
defer m.Cmd(mdb.MODIFY, CHANNEL, "", mdb.HASH, kit.MDB_HASH, h, kit.MDB_STATUS, tcp.CLOSE)
|
||||
_ssh_close(m, c, channel)
|
||||
})
|
||||
|
@ -7,6 +7,8 @@ import (
|
||||
"golang.org/x/crypto/ssh"
|
||||
)
|
||||
|
||||
type Winsize struct{ Height, Width, x, y uint16 }
|
||||
|
||||
func _ssh_size(fd uintptr, b []byte) {
|
||||
}
|
||||
func _ssh_handle(m *ice.Message, meta map[string]string, c net.Conn, channel ssh.Channel, requests <-chan *ssh.Request) {
|
||||
|
@ -22,7 +22,7 @@ func _ssh_session(m *ice.Message, h string, client *ssh.Client) (*ssh.Session, e
|
||||
m.Assert(e)
|
||||
|
||||
m.Go(func() {
|
||||
buf := make([]byte, 4096)
|
||||
buf := make([]byte, ice.MOD_BUFS)
|
||||
for {
|
||||
n, e := out.Read(buf)
|
||||
if e != nil {
|
||||
@ -36,8 +36,7 @@ func _ssh_session(m *ice.Message, h string, client *ssh.Client) (*ssh.Session, e
|
||||
})
|
||||
|
||||
m.Richs(SESSION, "", h, func(key string, value map[string]interface{}) {
|
||||
kit.Value(value, kit.Keym(OUTPUT), out)
|
||||
kit.Value(value, kit.Keym(INPUT), in)
|
||||
kit.Value(value, kit.Keym(OUTPUT), out, kit.Keym(INPUT), in)
|
||||
})
|
||||
|
||||
return session, nil
|
||||
@ -68,6 +67,7 @@ func init() {
|
||||
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.Option(mdb.FIELDS, "time,hash,status,count,connect")
|
||||
m.Cmdy(mdb.PRUNES, SESSION, "", mdb.HASH, kit.MDB_STATUS, tcp.ERROR)
|
||||
m.Cmdy(mdb.PRUNES, SESSION, "", mdb.HASH, kit.MDB_STATUS, tcp.CLOSE)
|
||||
}},
|
||||
@ -75,18 +75,20 @@ func init() {
|
||||
m.Richs(SESSION, "", m.Option(kit.MDB_HASH), func(key string, value map[string]interface{}) {
|
||||
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)
|
||||
w.Write([]byte(m.Option(CMD) + "\n"))
|
||||
}
|
||||
})
|
||||
m.ProcessRefresh("300ms")
|
||||
}},
|
||||
"repeat": {Name: "repeat", Help: "执行", Hand: func(m *ice.Message, arg ...string) {
|
||||
m.Cmdy(SESSION, kit.MDB_ACTION, ctx.COMMAND, CMD, m.Option("text"))
|
||||
}},
|
||||
}, 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")
|
||||
m.Fields(len(arg) == 0, "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("", mdb.REMOVE, value[kit.MDB_STATUS] == tcp.CLOSE))
|
||||
m.PushButton(kit.Select("", ctx.COMMAND, value[kit.MDB_STATUS] == tcp.OPEN), mdb.REMOVE)
|
||||
})
|
||||
}
|
||||
return
|
||||
@ -94,6 +96,9 @@ func init() {
|
||||
|
||||
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.Table(func(index int, value map[string]string, head []string) {
|
||||
m.PushButton(kit.Select("", "repeat", value["type"] == "cmd"))
|
||||
})
|
||||
}},
|
||||
},
|
||||
})
|
||||
|
@ -11,24 +11,17 @@ const SSH = "ssh"
|
||||
var Index = &ice.Context{Name: SSH, Help: "终端模块", Commands: map[string]*ice.Command{
|
||||
ice.CTX_INIT: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
|
||||
m.Load()
|
||||
m.Conf(SOURCE, kit.Keys(kit.MDB_HASH, STDIO, kit.MDB_META, kit.MDB_NAME), STDIO)
|
||||
m.Conf(SOURCE, kit.Keys(kit.MDB_HASH, STDIO, kit.MDB_META, kit.MDB_TIME), m.Time())
|
||||
m.Richs(SESSION, "", kit.MDB_FOREACH, func(key string, value map[string]interface{}) {
|
||||
kit.Value(value, kit.Keym(kit.MDB_STATUS), tcp.CLOSE)
|
||||
})
|
||||
m.Richs(CHANNEL, "", kit.MDB_FOREACH, func(key string, value map[string]interface{}) {
|
||||
kit.Value(value, kit.Keym(kit.MDB_STATUS), tcp.CLOSE)
|
||||
})
|
||||
}},
|
||||
ice.CTX_EXIT: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
|
||||
if _, ok := m.Target().Server().(*Frame); ok {
|
||||
m.Done(true)
|
||||
}
|
||||
m.Richs(CHANNEL, "", kit.MDB_FOREACH, func(key string, value map[string]interface{}) {
|
||||
kit.Value(value, kit.Keym(kit.MDB_STATUS), tcp.CLOSE)
|
||||
})
|
||||
m.Richs(SESSION, "", kit.MDB_FOREACH, func(key string, value map[string]interface{}) {
|
||||
kit.Value(value, kit.Keym(kit.MDB_STATUS), tcp.CLOSE)
|
||||
})
|
||||
|
||||
m.Richs(SOURCE, "", STDIO, func(key string, value map[string]interface{}) {
|
||||
m.Conf(SOURCE, kit.Keys(kit.MDB_HASH), "")
|
||||
m.Conf(SOURCE, kit.Keys(kit.MDB_HASH, key), value)
|
||||
})
|
||||
m.Save()
|
||||
}},
|
||||
}}
|
||||
@ -36,6 +29,6 @@ var Index = &ice.Context{Name: SSH, Help: "终端模块", Commands: map[string]*
|
||||
func init() {
|
||||
ice.Index.Register(Index, &Frame{},
|
||||
CONNECT, SESSION, SERVICE, CHANNEL,
|
||||
SOURCE, TARGET, PROMPT, RETURN,
|
||||
SOURCE, TARGET, PROMPT, PRINTF, SCREEN, RETURN,
|
||||
)
|
||||
}
|
||||
|
@ -5,10 +5,10 @@ refer `
|
||||
源码 https://github.com/openssh/openssh-portable
|
||||
`
|
||||
|
||||
field "服务" ssh.service
|
||||
field "通道" ssh.channel
|
||||
field "连接" ssh.connect
|
||||
field "会话" ssh.session
|
||||
field "服务" ssh.service
|
||||
field "通道" ssh.channel
|
||||
|
||||
field "脚本" ssh.source
|
||||
field "模块" ssh.target
|
||||
@ -16,4 +16,3 @@ field "提示" ssh.prompt
|
||||
field "输出" ssh.printf
|
||||
field "屏显" ssh.screen
|
||||
|
||||
|
||||
|
13
misc.go
13
misc.go
@ -1,8 +1,10 @@
|
||||
package ice
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"os"
|
||||
"path"
|
||||
"strings"
|
||||
"time"
|
||||
@ -345,3 +347,14 @@ func (m *Message) Upload(dir string) {
|
||||
}
|
||||
|
||||
func (m *Message) OptionFields(str string) { m.Option("fields", str) }
|
||||
func (m *Message) OptionLoad(file string) *Message {
|
||||
if f, e := os.Open(file); e == nil {
|
||||
defer f.Close()
|
||||
|
||||
var data interface{}
|
||||
json.NewDecoder(f).Decode(&data)
|
||||
|
||||
kit.Fetch(data, func(key string, value interface{}) { m.Option(key, kit.Simple(value)) })
|
||||
}
|
||||
return m
|
||||
}
|
||||
|
2
type.go
2
type.go
@ -116,7 +116,7 @@ func (c *Context) cmd(m *Message, cmd *Command, key string, arg ...string) *Mess
|
||||
}
|
||||
|
||||
m.meta[MSG_DETAIL] = kit.Simple(key, arg)
|
||||
if m.Hand = true; len(arg) > 1 && arg[0] == "action" && cmd.Action != nil {
|
||||
if m.Hand = true; len(arg) > 1 && arg[0] == kit.MDB_ACTION && cmd.Action != nil {
|
||||
if h, ok := cmd.Action[arg[1]]; ok {
|
||||
return c._hand(m, cmd, key, arg[1], h, arg[2:]...)
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user