|
@@ -1,81 +1,194 @@
|
|
|
package main
|
|
|
|
|
|
import (
|
|
|
+ "encoding/base64"
|
|
|
"fmt"
|
|
|
"os"
|
|
|
"os/user"
|
|
|
"regexp"
|
|
|
"strings"
|
|
|
|
|
|
- "git.wecise.com/wecise/common/logger"
|
|
|
+ "git.wecise.com/wecise/odbserver/matrix/logger"
|
|
|
+ "gopkg.in/yaml.v2"
|
|
|
)
|
|
|
|
|
|
func init() {
|
|
|
logger.SetConsole(true)
|
|
|
- logger.SetLevel(logger.INFO)
|
|
|
+ logger.SetLevel(logger.TRACE)
|
|
|
+ logger.SetFormat("yyyy-MM-dd HH:mm:SS.sss [level] msg")
|
|
|
}
|
|
|
|
|
|
-func uch() (u, c, h string, o bool) {
|
|
|
+func uchi() (u, c, h string, i int) {
|
|
|
if len(os.Args) < 2 {
|
|
|
return
|
|
|
}
|
|
|
- if regexp.MustCompile(`p=.+`).MatchString(os.Args[1]) {
|
|
|
+ if msi := regexp.MustCompile(`^([^:]+):(.*)@([^@]*)$`).FindStringSubmatchIndex(os.Args[1]); msi != nil {
|
|
|
+ u = os.Args[1][msi[2]:msi[3]]
|
|
|
+ c = "=" + os.Args[1][msi[4]:msi[5]]
|
|
|
+ h = os.Args[1][msi[6]:msi[7]]
|
|
|
+ i = 2
|
|
|
+ return
|
|
|
+ }
|
|
|
+ if msi := regexp.MustCompile(`^([^:]+)@([^@]*)$`).FindStringSubmatchIndex(os.Args[1]); msi != nil {
|
|
|
+ u = os.Args[1][msi[2]:msi[3]]
|
|
|
+ h = os.Args[1][msi[6]:msi[7]]
|
|
|
+ i = 2
|
|
|
+ } else if os.Args[1][0] != '-' && strings.Index(os.Args[1], "=") < 0 {
|
|
|
+ h = os.Args[1]
|
|
|
+ i = 2
|
|
|
+ } else {
|
|
|
+ i = 1
|
|
|
+ }
|
|
|
+ if u == "" {
|
|
|
user, e := user.Current()
|
|
|
if e != nil {
|
|
|
logger.Error(e)
|
|
|
- return
|
|
|
+ return "", "", "", 0
|
|
|
}
|
|
|
u = user.Username
|
|
|
- c = os.Args[1][2:]
|
|
|
+ }
|
|
|
+ if h == "" {
|
|
|
h = "127.0.0.1"
|
|
|
- o = true
|
|
|
- return
|
|
|
}
|
|
|
- uch := strings.SplitN(os.Args[1], ":", 2)
|
|
|
- if len(uch) < 2 {
|
|
|
- return
|
|
|
+ return
|
|
|
+}
|
|
|
+
|
|
|
+type KV struct{ Key, Val string }
|
|
|
+
|
|
|
+func parseArgs(args []string) (kvs []*KV) {
|
|
|
+ argk := ""
|
|
|
+ argv := ""
|
|
|
+ for _, arg := range args {
|
|
|
+ if argk != "" {
|
|
|
+ argv = arg
|
|
|
+ } else if regexp.MustCompile(`^\-\w+$`).MatchString(arg) {
|
|
|
+ argk = arg[1:]
|
|
|
+ continue
|
|
|
+ } else {
|
|
|
+ kv := strings.SplitN(arg, "=", 2)
|
|
|
+ if len(kv) == 2 {
|
|
|
+ argk = kv[0]
|
|
|
+ argv = kv[1]
|
|
|
+ } else {
|
|
|
+ argk = ""
|
|
|
+ argv = arg
|
|
|
+ }
|
|
|
+ }
|
|
|
+ kvs = append(kvs, &KV{argk, argv})
|
|
|
+ argk, argv = "", ""
|
|
|
}
|
|
|
- n := strings.LastIndex(uch[1], "@")
|
|
|
- if n < 0 {
|
|
|
- return
|
|
|
+ if argk != "" {
|
|
|
+ kvs = append(kvs, &KV{argk, argv})
|
|
|
}
|
|
|
- return uch[0], uch[1][:n], uch[1][n+1:], true
|
|
|
+ return
|
|
|
}
|
|
|
|
|
|
func main() {
|
|
|
- u, c, h, o := uch()
|
|
|
- if !o {
|
|
|
+ u, c, h, i := uchi()
|
|
|
+ if i == 0 {
|
|
|
fmt.Println("usage:")
|
|
|
- fmt.Println(" msh [user:code@host]|[p=password] [[c=]command [p=password] [[r=regexp] [o=output]]...]...")
|
|
|
+ fmt.Println(" msh user:password@host|p=password|a=passcode [[c=]command [p=password|a=passcode] [x=cmd-end-regexp] [[r=regexp] [o=output|n=outputline]]...]...")
|
|
|
+ fmt.Println(" a=passcode should be base64 encoded, or use p=password")
|
|
|
+ fmt.Println(" debug info include: p(progress) a(argments) m(match) 1(all)")
|
|
|
return
|
|
|
}
|
|
|
-
|
|
|
- cmds := []*Command{{Cmd: "", Password: c, Regexp: []*Regexp{{Regexp: nil, Output: ""}}}}
|
|
|
- for i := 2; i < len(os.Args); i++ {
|
|
|
- arg := os.Args[i]
|
|
|
- kv := strings.SplitN(arg, "=", 2)
|
|
|
- var cmd string
|
|
|
- switch kv[0] {
|
|
|
- case "cmd", "command", "c":
|
|
|
- cmd = kv[1]
|
|
|
+ kvs := parseArgs(os.Args[i:])
|
|
|
+ if c == "" {
|
|
|
+ for _, kv := range kvs {
|
|
|
+ if kv.Key == "a" {
|
|
|
+ c = kv.Val
|
|
|
+ if c == "" {
|
|
|
+ c = "="
|
|
|
+ }
|
|
|
+ break
|
|
|
+ }
|
|
|
+ if kv.Key == "p" {
|
|
|
+ c = "=" + kv.Val
|
|
|
+ break
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ p := c
|
|
|
+ if p[0:1] == "=" {
|
|
|
+ p = p[1:]
|
|
|
+ } else {
|
|
|
+ x, e := base64.RawStdEncoding.DecodeString(p)
|
|
|
+ if e == nil {
|
|
|
+ p = string(x)
|
|
|
+ }
|
|
|
+ // else 不是Base64编码,保持原值
|
|
|
+ }
|
|
|
+ // explainArgs key, val
|
|
|
+ cmds := []*Command{{Cmd: "ssh " + u + ":" + p + "@" + h, Password: c, Regexps: []*Matcher{{Regexp: nil, Output: ""}}, Endregx: regxprompt}}
|
|
|
+ for _, kv := range kvs {
|
|
|
+ key, val := kv.Key, kv.Val
|
|
|
+ switch key {
|
|
|
+ case "", "cmd", "command", "c":
|
|
|
+ cmds = append(cmds, &Command{Cmd: val, Password: c, Regexps: []*Matcher{{Regexp: nil, Output: ""}}, Endregx: regxprompt})
|
|
|
+ case "ry":
|
|
|
+ re, err := regexp.Compile(val)
|
|
|
+ if err != nil {
|
|
|
+ logger.Error("arg", i, err)
|
|
|
+ return
|
|
|
+ } else {
|
|
|
+ regxyesno = &Regexp{re}
|
|
|
+ }
|
|
|
+ case "rc":
|
|
|
+ re, err := regexp.Compile(val)
|
|
|
+ if err != nil {
|
|
|
+ logger.Error("arg", i, err)
|
|
|
+ return
|
|
|
+ } else {
|
|
|
+ regxpassword = &Regexp{re}
|
|
|
+ }
|
|
|
+ case "rp":
|
|
|
+ re, err := regexp.Compile(val)
|
|
|
+ if err != nil {
|
|
|
+ logger.Error("arg", i, err)
|
|
|
+ return
|
|
|
+ } else {
|
|
|
+ regxprompt = &Regexp{re}
|
|
|
+ }
|
|
|
case "password", "code", "pass", "p":
|
|
|
- cmds[len(cmds)-1].Password = kv[1]
|
|
|
- continue
|
|
|
+ cmds[len(cmds)-1].Password = "=" + val
|
|
|
+ case "passcode", "b64code", "a":
|
|
|
+ cmds[len(cmds)-1].Password = val
|
|
|
case "re", "r", "regex":
|
|
|
- re, err := regexp.Compile(kv[1])
|
|
|
- if err != nil {
|
|
|
- logger.Error(err)
|
|
|
+ if val == "" {
|
|
|
+ cmds[len(cmds)-1].Regexps = append(cmds[len(cmds)-1].Regexps, &Matcher{Regexp: nil})
|
|
|
} else {
|
|
|
- cmds[len(cmds)-1].Regexp = append(cmds[len(cmds)-1].Regexp, &Regexp{Regexp: re})
|
|
|
+ re, err := regexp.Compile(val)
|
|
|
+ if err != nil {
|
|
|
+ logger.Error("arg", i, err)
|
|
|
+ return
|
|
|
+ } else {
|
|
|
+ cmds[len(cmds)-1].Regexps = append(cmds[len(cmds)-1].Regexps, &Matcher{Regexp: &Regexp{re}})
|
|
|
+ }
|
|
|
+ }
|
|
|
+ case "x", "end":
|
|
|
+ if val == "" {
|
|
|
+ cmds[len(cmds)-1].Endregx = regxprompt
|
|
|
+ } else {
|
|
|
+ re, err := regexp.Compile(val)
|
|
|
+ if err != nil {
|
|
|
+ logger.Error("arg", i, err)
|
|
|
+ return
|
|
|
+ } else {
|
|
|
+ cmds[len(cmds)-1].Endregx = &Regexp{re}
|
|
|
+ }
|
|
|
}
|
|
|
- continue
|
|
|
case "out", "o", "output":
|
|
|
- cmds[len(cmds)-1].Regexp[len(cmds[len(cmds)-1].Regexp)-1].Output = kv[1]
|
|
|
- continue
|
|
|
- default:
|
|
|
- cmd = arg
|
|
|
+ cmds[len(cmds)-1].Regexps[len(cmds[len(cmds)-1].Regexps)-1].Output += val
|
|
|
+ case "outln", "n", "outputline":
|
|
|
+ cmds[len(cmds)-1].Regexps[len(cmds[len(cmds)-1].Regexps)-1].Output += val + "\n"
|
|
|
+ case "debug", "d":
|
|
|
+ cmds[len(cmds)-1].Regexps[len(cmds[len(cmds)-1].Regexps)-1].Debug += val
|
|
|
}
|
|
|
- cmds = append(cmds, &Command{Cmd: cmd, Password: c, Regexp: []*Regexp{{Regexp: nil, Output: ""}}})
|
|
|
+ }
|
|
|
+ if strings.Index(cmds[0].Regexps[0].Debug, "a") >= 0 || strings.Index(cmds[0].Regexps[0].Debug, "1") >= 0 {
|
|
|
+ //bs, _ := json.MarshalIndent(cmds, "", " ")
|
|
|
+ bs, _ := yaml.Marshal(cmds)
|
|
|
+ logger.Debug("arguments:\n" + string(bs))
|
|
|
}
|
|
|
node := &Node{
|
|
|
Name: "x",
|
|
@@ -85,7 +198,7 @@ func main() {
|
|
|
Port: 22,
|
|
|
KeyPath: "",
|
|
|
Passphrase: "",
|
|
|
- Password: c,
|
|
|
+ Password: p,
|
|
|
Commands: cmds,
|
|
|
Children: []*Node{},
|
|
|
Jump: []*Node{},
|