Example #1
0
File: parse.go Project: rprp/mssh
func parse(filename string) (sshs []SshClient, err error) {

	var sshcli SshClient
	content, err := ioutil.ReadFile(filename)
	if err != nil {
		return nil, err
	}
	sshclients := strings.Split(string(content), "\n")
	//	sshclients := sshclients[:len(sshclients) - 1]
	for _, v := range sshclients {
		if len(v) == 0 {
			continue
		}
		sshfields := strings.Fields(v)
		for i, v := range sshfields {
			sshfields[i] = strings.TrimSpace(v)
		}
		if len(sshfields) == 1 {
			sshcli.Hostaddr = sshfields[0]
			sshcli.Username = gUsername
			sshcli.Password = gPassword
			sshcli.Cmd = gCommand
		} else if len(sshfields) == 2 {
			sshcli.Hostaddr = sshfields[0]
			sshcli.Username = sshfields[1]
			sshcli.Password = gPassword
			sshcli.Cmd = gCommand
		} else if len(sshfields) == 3 {
			sshcli.Hostaddr = sshfields[0]
			sshcli.Username = sshfields[1]
			sshcli.Password = sshfields[2]
			sshcli.Cmd = gCommand
		} else if len(sshfields) >= 4 {
			sshcli.Hostaddr = sshfields[0]
			sshcli.Username = sshfields[1]
			sshcli.Password = sshfields[2]
			sshcli.Cmd = strings.Join(sshfields[3:], " ")
			sshcli.Cmd = helper.Abs(sshcli.Cmd)
			vprintf("%#v\n", sshcli.Cmd)
		}

		sshs = append(sshs, sshcli)
	}

	return
}
Example #2
0
File: mssh.go Project: rprp/mssh
func main() {
	flag.Usage = usage
	flag.Parse()

	//	SetLog()
	//	defer log4go.Close()

	args := flag.Args()
	argnums := flag.NArg()

	if flag.NArg() < 1 && flag.NFlag() < 1 {
		usage()
	}

	if argnums >= 1 {
		switch args[0] {
		case "help":
			usage()
		case "version":
			version()
			os.Exit(2)
		case "&", "|", "<", ">":

		default:
			if args[argnums-1] == "&" {
				args = args[:argnums-1]
			}

		}
	}

	var err error

	if *infile == "" {
		fmt.Println("please input your infile which included 'hostaddr username password command' one per line")
		usage()
	} else if !com.IsExist(*infile) {
		fmt.Printf("not found input file: %s\n", *infile)
		usage()
	}

	if *cfg == "" {
		gCfg = "./mssh.conf"
	} else {
		gCfg = *cfg
	}

	if !parseconf(gCfg) {
		fmt.Printf("init conf file %s failed, exit\n", *cfg)
		os.Exit(2)
	}

	if *cmd != "" {
		if len(args) > 0 {
			gCommand = fmt.Sprintf("%s %s", *cmd, strings.Join(args, " "))
		} else {
			if *shellmode {
				curpath, _ := os.Getwd()
				if !strings.Contains(*cmd, "/") {
					*cmd = curpath + "/" + *cmd
				}
				gCommand = fmt.Sprintf("%s %s", "/bin/bash", *cmd)
			} else {
				gCommand = *cmd
			}
		}
	}

	gCommand = helper.Abs(gCommand)
	vprintf("gCommnad: %s\n", gCommand)
	vprintf("gUsername: %s\n", gUsername)
	vprintf("gPassword: %s\n", gPassword)
	vprintf("gTimeout: %v\n", gTimeout)

	sshobjs, err := parse(*infile)
	if err != nil {
		log.Fatal(err)
	}
	vprintf("%#v\n", sshobjs)

	if *n < 1 || *n > 10000 {
		*n = runtime.NumCPU()
	}

	cmdout, _, err := com.ExecCmd("logname")
	vprintf("cmdout: %s", cmdout)
	if err == nil {
		cmdout = strings.TrimSpace(cmdout)
		if len(gMaillist) == 0 {
			gMaillist = fmt.Sprintf("*****@*****.**", cmdout)
		}
	}
	vprintf("gMaillist: %s\n", gMaillist)

	//	basename := filepath.Base(*cmd)
	var r = []byte("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_")
	randomfname := string(helper.RandomCreateBytes(32, r...)) + ".sh"
	vprintf("randomfname: %s\n", randomfname)

	chFirst := make(chan SshClient, *n)
	//	chSecond := make(chan SshClient, *n)
	oldtime := time.Now()
	scpTout := fmt.Sprintf("ConnectTimeout=%d", gTimeout)

	go func() {
		defer close(chFirst)
		for i, _ := range sshobjs {
			if *israndompwd {
				sshobjs[i].Cmd = fmt.Sprintf("echo %s | passwd --stdin %s", sshobjs[i].Password, sshobjs[i].Username)
				vprintf("%#v\n", sshobjs[i])
			} else if *shellmode {

				com.ExecCmd("scp", "-o", scpTout, "-o", "BatchMode=yes", "-r", *cmd, fmt.Sprintf("%s:/tmp/%s", helper.GetHost(sshobjs[i].Hostaddr, ":"), randomfname))
				sshobjs[i].Cmd = fmt.Sprintf("/bin/bash /tmp/%s && /bin/rm -f /tmp/%s", randomfname, randomfname)
				vprintf("%#v\n", sshobjs[i])
			}
			chFirst <- sshobjs[i]
		}
	}()

	wg1 := new(sync.WaitGroup)
	wg2 := new(sync.WaitGroup)
	tryslice := make([]SshClient, 0)
	sem := make(chan struct{}, *n)
	mux := new(sync.Mutex)

	for i := 0; i < *n; i++ {
		wg1.Add(1)
		go func(ch chan SshClient) {
			defer wg1.Done()

			for v := range ch {
				vprintf("%#v\n", v)
				func(sshitem SshClient) {
					err, _, stdout, _ := sshutils.SshExec(sshitem.Hostaddr, sshitem.Username, sshitem.Password, sshitem.Cmd, gTimeout)
					if err != nil {
						mux.Lock()
						tryslice = append(tryslice, sshitem)
						mux.Unlock()
						return
					}

					mux.Lock()
					cnt++
					fmt.Println(strings.Repeat("*", 40), "[", cnt, "]", strings.Repeat("*", 40))
					fmt.Println(fmt.Sprintf("%s:\n%s\n", sshitem.Hostaddr, stdout))
					mux.Unlock()
				}(v)
			}
		}(chFirst)
	}

	wg1.Wait()

	//for /usr/bin/ssh execute shell cmds

	buf.WriteString("\nrunning results(error host lists):\n\n")

	for _, v := range tryslice {
		sem <- struct{}{}
		wg2.Add(1)
		go func(sshitem SshClient) {
			defer wg2.Done()
			err, _, stdout, _ := sshutils.SshCmdExec(sshitem.Hostaddr, sshitem.Username, sshitem.Password, sshitem.Cmd, gTimeout)
			if err != nil {
				log.Println("[/usr/bin/ssh]", sshitem.Hostaddr, err)
				//				log4go.Error("[/usr/bin/ssh] %s %v", sshitem.Hostaddr, err)
				buf.WriteString(sshitem.Hostaddr + "\n")
				<-sem
				return
			}

			mux.Lock()
			cnt++
			fmt.Println("[", cnt, "]", strings.Repeat("*", 80))
			fmt.Println(fmt.Sprintf("%s %s:\n%s\n", "[/usr/bin/ssh]", sshitem.Hostaddr, stdout))
			//			log4go.Info(fmt.Sprintf("%s %s:\n%s\n", "[/usr/bin/ssh]", sshitem.Hostaddr, stdout))
			mux.Unlock()
			<-sem
		}(v)

	}

	wg2.Wait()

	//kill ssh process which is timeout
	vprintf("Kill ssh for timeout\n")
	kill(sshutils.Cmds)

	errMsg := buf.String()
	htmlErrMsg := strings.Replace(errMsg, "\n", "<br>", -1)
	now := time.Now().String()
	title := gTitle
	mode := gMode
	execTime := time.Since(oldtime)
	totalTime := execTime.String()
	var body string
	if mode == "html" {
		body = now + "<br>" + gBody + "<br>" + htmlErrMsg + "<br>total time: " + totalTime
	} else {
		body = now + "\n" + gBody + "\n" + errMsg + "\ntotal time: " + totalTime
	}
	maillist := []string{gMaillist}

	config := fmt.Sprintf(`{"username":"******","password":"******","host":"%s","port":%d}`, mailUsername, mailPassword, mailHost, mailPort)

	mail := utils.NewEMail(config)
	mail.To = maillist
	mail.From = gFr_addr
	mail.Subject = title

	if mode == "html" {
		mail.HTML = body
	} else {
		mail.Text = body
	}

	if *ismail {
		err = mail.Send()
		if err != nil {
			log.Println("send mail failed:", err)
			goto LEAVE
		}

		fmt.Println("send mail successful")
	}

LEAVE:
	newtime := time.Since(oldtime)
	fmt.Println("run time:", newtime)

}