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

opt ssh.scripts

This commit is contained in:
shylinux 2021-06-01 06:58:45 +08:00
parent c714a7be57
commit 545ec26ea8
10 changed files with 165 additions and 125 deletions

View File

@ -170,9 +170,9 @@ func _list_select(m *ice.Message, prefix, chain, field, value string) {
}
}
})
if m.Option(FIELDS) != DETAIL {
m.SortIntR(kit.MDB_ID)
}
// if m.Option(FIELDS) != DETAIL {
// m.SortIntR(kit.MDB_ID)
// }
}
func _list_modify(m *ice.Message, prefix, chain string, field, value string, arg ...string) {
m.Grows(prefix, chain, field, value, func(index int, val map[string]interface{}) {
@ -415,6 +415,7 @@ const (
CACHE_LIMIT = "cache.limit"
CACHE_FIELD = "cache.field"
CACHE_VALUE = "cache.value"
CACHE_OFFEND = "cache.offend"
CACHE_CLEAR_ON_EXIT = "cache.clear.on.exit"
)

View File

@ -34,7 +34,7 @@ func _ssh_exec(m *ice.Message, cmd string, arg []string, env []string, tty io.Re
}
func _ssh_close(m *ice.Message, c net.Conn, channel ssh.Channel) {
defer channel.Close()
channel.Write([]byte(m.Conf(SERVICE, "meta.goodbye")))
channel.Write([]byte(m.Conf(SERVICE, kit.Keym(GOODBYE))))
}
func _ssh_watch(m *ice.Message, meta map[string]string, h string, input io.Reader, output io.Writer, display io.Writer) {
r, w := io.Pipe()
@ -77,11 +77,13 @@ func init() {
m.Cmdy(mdb.DELETE, CHANNEL, "", 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,hostport,tty,count")
m.Cmdy(mdb.PRUNES, SERVICE, "", mdb.HASH, kit.MDB_STATUS, tcp.ERROR)
m.Cmdy(mdb.PRUNES, CHANNEL, "", 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,username,hostname,hostport,tty,count")
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))
@ -90,7 +92,8 @@ func init() {
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, CHANNEL, kit.Keys(kit.MDB_HASH, arg[0]), mdb.LIST, kit.MDB_ID, arg[1:])
}},
},

View File

@ -172,6 +172,13 @@ func init() {
CONNECT: {Name: CONNECT, Help: "连接", Value: kit.Data()},
},
Commands: map[string]*ice.Command{
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)
}
})
}},
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...)

View File

@ -21,17 +21,10 @@ func Render(msg *ice.Message, cmd string, args ...interface{}) {
switch arg := kit.Simple(args...); cmd {
case ice.RENDER_VOID:
case ice.RENDER_RESULT:
fmt.Fprint(msg.O, msg.Result())
case ice.RENDER_QRCODE:
fmt.Fprint(msg.O, msg.Cmdx("cli.qrcode", kit.Format(args[0], args[1:]...)))
case ice.RENDER_DOWNLOAD:
if f, e := os.Open(arg[0]); e == nil {
defer f.Close()
io.Copy(msg.O, f)
if len(arg) > 0 {
msg.Resultv(arg)
}
fmt.Fprint(msg.O, msg.Result())
default:
// 转换结果
@ -39,7 +32,6 @@ func Render(msg *ice.Message, cmd string, args ...interface{}) {
if res == "" {
res = msg.Table().Result()
}
args = append(args, "length:", len(res))
// 输出结果
if fmt.Fprint(msg.O, res); !strings.HasSuffix(res, "\n") {
@ -48,11 +40,12 @@ func Render(msg *ice.Message, cmd string, args ...interface{}) {
}
}
func Script(m *ice.Message, name string) io.Reader {
if strings.Contains(m.Option("_script"), "/") {
name = path.Join(path.Dir(m.Option("_script")), name)
if strings.Contains(m.Option(ice.MSG_SCRIPT), "/") {
name = path.Join(path.Dir(m.Option(ice.MSG_SCRIPT)), name)
}
m.Option("_script", name)
m.Option(ice.MSG_SCRIPT, name)
// 本地文件
back := kit.Split(m.Option(nfs.DIR_ROOT))
for i := len(back) - 1; i >= 0; i-- {
if s, e := os.Open(path.Join(path.Join(back[:i]...), name)); e == nil {
@ -64,24 +57,26 @@ func Script(m *ice.Message, name string) io.Reader {
}
switch strings.Split(name, "/")[0] {
case "etc", "var":
case kit.SSH_ETC, kit.SSH_VAR:
m.Warn(true, ice.ErrNotFound)
return nil
}
// 打包文件
if b, ok := ice.BinPack["/"+name]; ok {
m.Info("binpack %v %v", len(b), name)
return bytes.NewReader(b)
}
// 远程文件
if msg := m.Cmd("web.spide", "dev", "GET", path.Join("/share/local/", name)); msg.Result(0) != ice.ErrWarn {
bio := bytes.NewBuffer([]byte(msg.Result()))
return bio
return bytes.NewBuffer([]byte(msg.Result()))
}
if strings.HasPrefix(name, "usr") {
// 源码文件
if strings.HasPrefix(name, kit.SSH_USR) {
ls := strings.Split(name, "/")
m.Cmd("web.code.git.repos", ls[1], "usr/"+ls[1])
m.Cmd("web.code.git.repos", ls[1], path.Join(kit.SSH_USR, ls[1]))
if s, e := os.Open(name); e == nil {
return s
}
@ -93,6 +88,8 @@ type Frame struct {
source string
target *ice.Context
stdout io.Writer
stdin io.Reader
pipe io.Writer
count int
ps1 []string
@ -113,11 +110,11 @@ func (f *Frame) prompt(m *ice.Message, list ...string) *Frame {
fmt.Fprintf(f.stdout, "\r")
for _, v := range list {
switch v {
case "count":
case kit.MDB_COUNT:
fmt.Fprintf(f.stdout, "%d", f.count)
case "time":
case kit.MDB_TIME:
fmt.Fprintf(f.stdout, time.Now().Format("15:04:05"))
case "target":
case TARGET:
fmt.Fprintf(f.stdout, f.target.Name)
default:
fmt.Fprintf(f.stdout, v)
@ -135,7 +132,7 @@ func (f *Frame) printf(m *ice.Message, res string, arg ...interface{}) *Frame {
}
func (f *Frame) option(m *ice.Message, ls []string) []string {
ln := []string{}
m.Option("cache.limit", 10)
m.Option(mdb.CACHE_LIMIT, 10)
for i := 0; i < len(ls); i++ {
if ls[i] == "--" {
ln = append(ln, ls[i+1:]...)
@ -161,11 +158,10 @@ func (f *Frame) option(m *ice.Message, ls []string) []string {
return ln
}
func (f *Frame) change(m *ice.Message, ls []string) []string {
if len(ls) == 1 && ls[0] == "~" {
// 模块列表
if len(ls) == 1 && ls[0] == "~" { // 模块列表
ls = []string{"context"}
} else if len(ls) > 0 && strings.HasPrefix(ls[0], "~") {
// 切换模块
} else if len(ls) > 0 && strings.HasPrefix(ls[0], "~") { // 切换模块
target := ls[0][1:]
if ls = ls[1:]; len(target) == 0 && len(ls) > 0 {
target, ls = ls[0], ls[1:]
@ -231,21 +227,21 @@ func (f *Frame) parse(m *ice.Message, line string) string {
}
return ""
}
func (f *Frame) scan(m *ice.Message, h, line string, r io.Reader) *Frame {
m.Option("ssh.return", func() { f.exit = true })
f.ps1 = kit.Simple(m.Confv("prompt", "meta.PS1"))
f.ps2 = kit.Simple(m.Confv("prompt", "meta.PS2"))
func (f *Frame) scan(m *ice.Message, h, line string) *Frame {
m.Option(kit.Keycb(RETURN), func() { f.exit = true })
f.ps1 = kit.Simple(m.Confv(PROMPT, kit.Keym(PS1)))
f.ps2 = kit.Simple(m.Confv(PROMPT, kit.Keym(PS2)))
ps := f.ps1
m.I, m.O = r, f.stdout
bio := bufio.NewScanner(r)
m.Sleep("300ms")
m.I, m.O = f.stdin, f.stdout
bio := bufio.NewScanner(f.stdin)
for f.prompt(m, ps...); bio.Scan() && !f.exit; f.prompt(m, ps...) {
if h == STDIO && len(bio.Text()) == 0 {
continue // 空行
}
// m.Cmdx(mdb.INSERT, SOURCE, kit.Keys(kit.MDB_HASH, h), mdb.LIST, kit.MDB_TEXT, bio.Text())
m.Cmdx(mdb.INSERT, SOURCE, kit.Keys(kit.MDB_HASH, h), mdb.LIST, kit.MDB_TEXT, bio.Text())
f.count++
if len(bio.Text()) == 0 {
@ -284,40 +280,43 @@ func (f *Frame) Spawn(m *ice.Message, c *ice.Context, arg ...string) ice.Server
func (f *Frame) Start(m *ice.Message, arg ...string) bool {
f.source, f.target = kit.Select(STDIO, arg, 0), m.Target()
var r io.Reader
switch m.Cap(ice.CTX_STREAM, f.source) {
case STDIO: // 终端交互
r, f.stdout = os.Stdin, os.Stdout
r, w, _ := os.Pipe()
m.Go(func() { io.Copy(w, os.Stdin) })
f.stdin, f.stdout = r, os.Stdout
f.pipe = w
m.Option(ice.MSG_OPTS, ice.MSG_USERNAME)
aaa.UserRoot(m)
default:
default: // 脚本文件
f.target = m.Source()
if strings.HasPrefix(f.source, "/dev") {
r, f.stdout = m.I, m.O
f.stdin, f.stdout = m.I, m.O
break
}
buf := bytes.NewBuffer(make([]byte, 0, 4096))
buf := bytes.NewBuffer(make([]byte, 0, ice.MOD_BUFS))
defer func() { m.Echo(buf.String()) }()
if s := Script(m, f.source); s != nil {
r, f.stdout = s, buf
f.stdin, f.stdout = s, buf
break
}
// 查找失败
return true
}
// 解析脚本
if f.count = 1; f.source == STDIO {
// m.Option("_disable_log", "true")
f.count = kit.Int(m.Conf(SOURCE, "hash.stdio.meta.count")) + 1
f.scan(m, STDIO, "", r)
f.count = kit.Int(m.Conf(SOURCE, kit.Keys("hash.stdio.meta.count"))) + 1
f.scan(m, STDIO, "")
} else {
h := m.Cmdx(mdb.INSERT, SOURCE, "", mdb.HASH, kit.MDB_NAME, f.source)
f.scan(m, h, "", r)
f.scan(m, h, "")
}
return true
}
@ -327,60 +326,80 @@ func (f *Frame) Close(m *ice.Message, arg ...string) bool {
const (
STDIO = "stdio"
PS1 = "PS1"
PS2 = "PS2"
)
const (
SOURCE = "source"
TARGET = "target"
PROMPT = "prompt"
PRINTF = "printf"
RETURN = "return"
SCREEN = "screen"
)
func init() {
Index.Merge(&ice.Context{
Configs: map[string]*ice.Config{
SOURCE: {Name: SOURCE, Help: "加载脚本", Value: kit.Dict()},
SOURCE: {Name: SOURCE, Help: "加载脚本", Value: kit.Data(kit.MDB_SHORT, kit.MDB_NAME)},
PROMPT: {Name: PROMPT, Help: "命令提示", Value: kit.Data(
"PS1", []interface{}{"\033[33;44m", "count", "[", "time", "]", "\033[5m", "target", "\033[0m", "\033[44m", ">", "\033[0m ", "\033[?25h", "\033[32m"},
"PS2", []interface{}{"count", " ", "target", "> "},
PS1, []interface{}{"\033[33;44m", kit.MDB_COUNT, "[", kit.MDB_TIME, "]", "\033[5m", TARGET, "\033[0m", "\033[44m", ">", "\033[0m ", "\033[?25h", "\033[32m"},
PS2, []interface{}{kit.MDB_COUNT, " ", TARGET, "> "},
)},
},
Commands: map[string]*ice.Command{
SOURCE: {Name: "source hash id auto", Help: "脚本解析", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
if len(arg) > 0 && strings.HasSuffix(arg[0], ".shy") {
SOURCE: {Name: "source hash id limit offend auto", Help: "脚本解析", 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
}
if len(arg) == 0 {
m.Option(mdb.FIELDS, "time,hash,name,count")
if len(arg) == 0 { // 脚本列表
m.Fields(len(arg) == 0, "time,hash,name,count")
m.Cmdy(mdb.SELECT, SOURCE, "", mdb.HASH)
m.Sort(kit.MDB_NAME)
return
}
if arg[0] == STDIO {
m.Option("_control", "_page")
if m.Option(mdb.CACHE_OFFEND, kit.Select("0", arg, 3)); arg[0] == STDIO {
m.Option(mdb.CACHE_LIMIT, kit.Select("10", arg, 2))
} else {
m.Option("cache.limit", "-1")
m.Option(mdb.CACHE_LIMIT, kit.Select("-1", arg, 2))
}
m.Option(mdb.FIELDS, kit.Select("time,id,text", mdb.DETAIL, len(arg) > 1))
// 命令列表
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.Sort(kit.MDB_ID)
}},
TARGET: {Name: "target name", Help: "当前模块", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
m.Search(arg[0], func(p *ice.Context, s *ice.Context, key string) {
TARGET: {Name: "target name 执行:button", Help: "当前模块", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
f := m.Target().Server().(*Frame)
f.target = s
m.Search(arg[0]+".", func(p *ice.Context, s *ice.Context, key string) { f.target = s })
f.prompt(m)
})
m.Echo(arg[0])
}},
PROMPT: {Name: "prompt arg...", Help: "命令提示", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
PROMPT: {Name: "prompt arg 执行:button", Help: "命令提示", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
f := m.Target().Server().(*Frame)
f.ps1 = arg
f.prompt(m)
m.Echo(arg[0])
}},
PRINTF: {Name: "printf 执行:button text:textarea", Help: "输出显示", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
f := m.Target().Server().(*Frame)
f.printf(m, arg[0])
m.Echo(arg[0])
}},
SCREEN: {Name: "screen 执行:button text:textarea", Help: "输出命令", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
f := m.Target().Server().(*Frame)
for _, line := range kit.Split(arg[0], "\n", "\n", "\n") {
f.printf(m, line+"\n")
fmt.Fprintf(f.pipe, line+"\n")
m.Sleep("300ms")
}
m.Echo(arg[0])
}},
RETURN: {Name: "return", Help: "结束脚本", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
switch cb := m.Optionv("ssh.return").(type) {
switch cb := m.Optionv(kit.Keycb(RETURN)).(type) {
case func():
cb()
}

View File

@ -12,6 +12,7 @@ import (
ice "github.com/shylinux/icebergs"
"github.com/shylinux/icebergs/base/aaa"
"github.com/shylinux/icebergs/base/cli"
"github.com/shylinux/icebergs/base/mdb"
"github.com/shylinux/icebergs/base/nfs"
"github.com/shylinux/icebergs/base/tcp"
@ -22,7 +23,6 @@ import (
func _ssh_meta(conn ssh.ConnMetadata) map[string]string {
return map[string]string{aaa.USERNAME: conn.User(), tcp.HOSTPORT: conn.RemoteAddr().String()}
}
func _ssh_config(m *ice.Message, h string) *ssh.ServerConfig {
config := &ssh.ServerConfig{
PublicKeyCallback: func(conn ssh.ConnMetadata, key ssh.PublicKey) (*ssh.Permissions, error) {
@ -51,22 +51,20 @@ func _ssh_config(m *ice.Message, h string) *ssh.ServerConfig {
},
PasswordCallback: func(conn ssh.ConnMetadata, password []byte) (*ssh.Permissions, error) {
meta, err := _ssh_meta(conn), errors.New(ice.ErrNotRight)
m.Richs(aaa.USER, "", conn.User(), func(k string, value map[string]interface{}) {
if string(password) == kit.Format(value[aaa.PASSWORD]) {
m.Log_AUTH(tcp.HOSTPORT, conn.RemoteAddr(), aaa.USERNAME, conn.User(), aaa.PASSWORD, strings.Repeat("*", len(kit.Format(value[aaa.PASSWORD]))))
if aaa.UserLogin(m, conn.User(), string(password)) {
m.Log_AUTH(tcp.HOSTPORT, conn.RemoteAddr(), aaa.USERNAME, conn.User(), aaa.PASSWORD, strings.Repeat("*", len(string(password))))
err = nil // 密码登录
}
})
return &ssh.Permissions{Extensions: meta}, err
},
BannerCallback: func(conn ssh.ConnMetadata) string {
m.Log_IMPORT(tcp.HOSTPORT, conn.RemoteAddr(), aaa.USERNAME, conn.User())
return m.Conf(SERVICE, "meta.welcome")
return m.Conf(SERVICE, kit.Keym(WELCOME))
},
}
if key, err := ssh.ParsePrivateKey([]byte(m.Cmdx(nfs.CAT, path.Join(os.Getenv("HOME"), m.Option("private"))))); m.Assert(err) {
if key, err := ssh.ParsePrivateKey([]byte(m.Cmdx(nfs.CAT, path.Join(os.Getenv(cli.HOME), m.Option(PRIVATE))))); m.Assert(err) {
config.AddHostKey(key)
}
return config
@ -91,26 +89,40 @@ func _ssh_accept(m *ice.Message, h string, c net.Conn) {
}
}
const (
WELCOME = "welcome"
GOODBYE = "goodbye"
PRIVATE = "private"
AUTHKEY = "authkey"
REQUEST = "request"
)
const SERVICE = "service"
func init() {
Index.Merge(&ice.Context{
Configs: map[string]*ice.Config{
SERVICE: {Name: SERVICE, Help: "服务", Value: kit.Data(
"welcome", "\r\nwelcome to context world\r\n",
"goodbye", "\r\ngoodbye of context world\r\n",
WELCOME, "\r\nwelcome to context world\r\n",
GOODBYE, "\r\ngoodbye of context world\r\n",
kit.MDB_SHORT, tcp.PORT,
)},
},
Commands: map[string]*ice.Command{
ice.CTX_INIT: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
m.Richs(SERVICE, "", 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(SERVICE, tcp.LISTEN, tcp.PORT, value[tcp.PORT], value)
}
})
}},
SERVICE: {Name: "service port id auto listen prunes", Help: "服务", Action: map[string]*ice.Action{
tcp.LISTEN: {Name: "listen port=9030 private=.ssh/id_rsa auth=.ssh/authorized_keys", Help: "监听", Hand: func(m *ice.Message, arg ...string) {
tcp.LISTEN: {Name: "listen port=9030 private=.ssh/id_rsa authkey=.ssh/authorized_keys", Help: "添加", Hand: func(m *ice.Message, arg ...string) {
if m.Richs(SERVICE, "", m.Option(tcp.PORT), func(key string, value map[string]interface{}) {
kit.Value(value, "meta.status", tcp.OPEN)
kit.Value(value, kit.Keym(kit.MDB_STATUS), tcp.OPEN)
}) == nil {
m.Cmd(mdb.INSERT, SERVICE, "", mdb.HASH, tcp.PORT, m.Option(tcp.PORT),
"private", m.Option("private"), "auth", m.Option("auth"), kit.MDB_STATUS, tcp.OPEN, arg)
m.Cmd(SERVICE, mdb.IMPORT, kit.MDB_FILE, m.Option("auth"))
PRIVATE, m.Option(PRIVATE), AUTHKEY, m.Option(AUTHKEY), kit.MDB_STATUS, tcp.OPEN, arg)
m.Cmd(SERVICE, mdb.IMPORT, AUTHKEY, m.Option(AUTHKEY))
}
m.Option(kit.Keycb(tcp.LISTEN), func(c net.Conn) { m.Go(func() { _ssh_accept(m, kit.Hashs(m.Option(tcp.PORT)), c) }) })
@ -120,53 +132,52 @@ func init() {
}},
mdb.INSERT: {Name: "insert text:textarea", Help: "添加", Hand: func(m *ice.Message, arg ...string) {
ls := kit.Split(m.Option(kit.MDB_TEXT))
if ls := kit.Split(m.Option(kit.MDB_TEXT)); len(ls) > 2 {
m.Cmdy(mdb.INSERT, SERVICE, kit.Keys(kit.MDB_HASH, kit.Hashs(m.Option(tcp.PORT))), mdb.LIST,
kit.MDB_TYPE, ls[0], kit.MDB_NAME, ls[len(ls)-1], kit.MDB_TEXT, strings.Join(ls[1:len(ls)-1], "+"))
}
}},
mdb.EXPORT: {Name: "export file=.ssh/authorized_keys", Help: "导出", Hand: func(m *ice.Message, arg ...string) {
mdb.EXPORT: {Name: "export authkey=.ssh/authorized_keys", Help: "导出", Hand: func(m *ice.Message, arg ...string) {
list := []string{}
m.Cmd(mdb.SELECT, SERVICE, kit.Keys(kit.MDB_HASH, kit.Hashs(m.Option(tcp.PORT))), mdb.LIST).Table(func(index int, value map[string]string, head []string) {
list = append(list, fmt.Sprintf("%s %s %s", value[kit.MDB_TYPE], value[kit.MDB_TEXT], value[kit.MDB_NAME]))
})
if len(list) > 0 {
m.Cmdy(nfs.SAVE, path.Join(os.Getenv("HOME"), m.Option(kit.MDB_FILE)), strings.Join(list, "\n")+"\n")
m.Cmdy(nfs.SAVE, path.Join(os.Getenv(cli.HOME), m.Option(AUTHKEY)), strings.Join(list, "\n")+"\n")
}
}},
mdb.IMPORT: {Name: "import file=.ssh/authorized_keys", Help: "导入", Hand: func(m *ice.Message, arg ...string) {
p := path.Join(os.Getenv("HOME"), m.Option(kit.MDB_FILE))
for _, pub := range strings.Split(m.Cmdx(nfs.CAT, p), "\n") {
if ls := kit.Split(pub); len(pub) > 10 {
m.Cmd(mdb.INSERT, SERVICE, kit.Keys(kit.MDB_HASH, kit.Hashs(m.Option(tcp.PORT))), mdb.LIST,
kit.MDB_TYPE, ls[0], kit.MDB_NAME, ls[len(ls)-1], kit.MDB_TEXT, strings.Join(ls[1:len(ls)-1], "+"))
}
mdb.IMPORT: {Name: "import authkey=.ssh/authorized_keys", Help: "导入", Hand: func(m *ice.Message, arg ...string) {
p := path.Join(os.Getenv(cli.HOME), m.Option(AUTHKEY))
for _, pub := range strings.Split(strings.TrimSpace(m.Cmdx(nfs.CAT, p)), "\n") {
m.Cmd(SERVICE, mdb.INSERT, kit.MDB_TEXT, pub)
}
m.Echo(p)
}},
mdb.PRUNES: {Name: "prunes", Help: "清理", Hand: func(m *ice.Message, arg ...string) {
m.Option(mdb.FIELDS, "time,port,status,private,authkey,count")
m.Cmdy(mdb.PRUNES, SERVICE, "", mdb.HASH, kit.MDB_STATUS, tcp.ERROR)
m.Cmdy(mdb.PRUNES, SERVICE, "", mdb.HASH, kit.MDB_STATUS, tcp.CLOSE)
}},
aaa.INVITE: {Name: "invite", Help: "邀请", Hand: func(m *ice.Message, arg ...string) {
u := kit.ParseURL(m.Option(ice.MSG_USERWEB))
m.Option("hostname", strings.Split(u.Host, ":")[0])
m.Option(cli.HOSTNAME, strings.Split(u.Host, ":")[0])
m.ProcessInner()
m.Option("_process", "_inner")
if buf, err := kit.Render(`
ssh {{.Option "user.name"}}@{{.Option "hostname"}} -p {{.Option "port"}}
`, m); err == nil {
m.Cmdy("web.wiki.spark", "shell", string(buf))
if buf, err := kit.Render(`ssh -p {{.Option "port"}} {{.Option "user.name"}}@{{.Option "hostname"}}`, m); err == nil {
m.EchoScript(string(buf))
}
}},
}, Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
if len(arg) == 0 {
m.Option(mdb.FIELDS, "time,status,port,private,auth,count")
if len(arg) == 0 { // 服务列表
m.Fields(len(arg) == 0, "time,port,status,private,authkey,count")
m.Cmdy(mdb.SELECT, SERVICE, "", mdb.HASH)
m.PushAction(mdb.IMPORT, mdb.INSERT, mdb.EXPORT, aaa.INVITE)
return
}
m.Option(mdb.FIELDS, kit.Select("time,id,type,name,text", mdb.DETAIL, len(arg) > 1))
// 公钥列表
m.Fields(len(arg) == 1, "time,id,type,name,text")
m.Cmdy(mdb.SELECT, SERVICE, kit.Keys(kit.MDB_HASH, kit.Hashs(arg[0])), mdb.LIST, kit.MDB_ID, arg[1:])
}},
},

View File

@ -10,6 +10,7 @@ import (
"unsafe"
ice "github.com/shylinux/icebergs"
"github.com/shylinux/icebergs/base/cli"
"github.com/shylinux/icebergs/base/mdb"
"github.com/shylinux/icebergs/base/tcp"
kit "github.com/shylinux/toolkits"
@ -28,7 +29,7 @@ func _ssh_handle(m *ice.Message, meta map[string]string, c net.Conn, channel ssh
defer m.Logs("dischan", tcp.HOSTPORT, c.RemoteAddr(), "->", c.LocalAddr())
shell := kit.Select("bash", os.Getenv("SHELL"))
list := []string{"PATH=" + os.Getenv("PATH")}
list := []string{cli.PATH + "=" + os.Getenv(cli.PATH)}
pty, tty, err := pty.Open()
if m.Warn(err != nil, err) {
@ -40,7 +41,7 @@ func _ssh_handle(m *ice.Message, meta map[string]string, c net.Conn, channel ssh
meta[CHANNEL] = h
for request := range requests {
m.Logs("request", tcp.HOSTPORT, c.RemoteAddr(), kit.MDB_TYPE, request.Type)
m.Logs(REQUEST, tcp.HOSTPORT, c.RemoteAddr(), kit.MDB_TYPE, request.Type)
switch request.Type {
case "pty-req":

View File

@ -1,7 +1,6 @@
package ssh
import (
"golang.org/x/crypto/ssh"
"io"
ice "github.com/shylinux/icebergs"
@ -9,6 +8,7 @@ import (
"github.com/shylinux/icebergs/base/mdb"
"github.com/shylinux/icebergs/base/tcp"
kit "github.com/shylinux/toolkits"
"golang.org/x/crypto/ssh"
)
func _ssh_session(m *ice.Message, h string, client *ssh.Client) (*ssh.Session, error) {

View File

@ -13,24 +13,16 @@ var Index = &ice.Context{Name: SSH, Help: "终端模块", Commands: map[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(SERVICE, "", kit.MDB_FOREACH, func(key string, value map[string]interface{}) {
value = kit.GetMeta(value)
m.Cmd(SERVICE, tcp.LISTEN, tcp.PORT, value[tcp.PORT], value)
})
}},
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, "meta.status", tcp.CLOSE)
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, "meta.status", tcp.CLOSE)
})
m.Richs(CONNECT, "", kit.MDB_FOREACH, func(key string, value map[string]interface{}) {
kit.Value(value, "status", tcp.CLOSE)
kit.Value(value, kit.Keym(kit.MDB_STATUS), tcp.CLOSE)
})
m.Richs(SOURCE, "", STDIO, func(key string, value map[string]interface{}) {

View File

@ -7,8 +7,13 @@ refer `
field "服务" ssh.service
field "通道" ssh.channel
field "连接" ssh.connect
field "会话" ssh.session
field "脚本" ssh.source
field "脚本" ssh.source
field "模块" ssh.target
field "提示" ssh.prompt
field "输出" ssh.printf
field "屏显" ssh.screen

View File

@ -73,6 +73,7 @@ const ( // MSG
MSG_RESULT = "result"
MSG_ALIAS = "_alias"
MSG_SCRIPT = "_script"
MSG_SOURCE = "_source"
MSG_TARGET = "_target"
MSG_HANDLE = "_handle"