func SerialRun(config map[string]interface{}, raw_host_arr []string, start, end int) error { host_arr := raw_host_arr[start:end] user, _ := config["User"].(string) pwd, _ := config["Password"].(string) keyfile, _ := config["Keyfile"].(string) cmd, _ := config["Cmd"].(string) args, _ := config["Args"].(string) timeout, _ := config["Timeout"].(int) // Format command cmd = format_cmd(cmd, args) printer, _ := config["Output"].(io.Writer) err_printer, _ := config["Errout"].(io.Writer) mgr, _ := job.NewManager() for index, h := range host_arr { s3h := sssh.NewS3h(h, user, pwd, keyfile, cmd, printer, err_printer, mgr) s3h.Timeout = timeout go func() { if _, err := mgr.Receive(-1); err == nil { report(err_printer, fmt.Sprintf("%d/%d ", index+1+start, len(raw_host_arr)), s3h.Host, true) mgr.Send(s3h.Host, map[string]interface{}{"FROM": job.MASTER_ID, "BODY": "CONTINUE"}) } else { mgr.Send(s3h.Host, map[string]interface{}{"FROM": job.MASTER_ID, "BODY": "STOP"}) } }() s3h.Work() } return nil }
func Interact(config map[string]interface{}, host string) { user, _ := config["User"].(string) pwd, _ := config["Password"].(string) keyfile, _ := config["Keyfile"].(string) cmd, _ := config["Cmd"].(string) printer, _ := config["Output"].(io.Writer) err_printer, _ := config["Errout"].(io.Writer) mgr, _ := job.NewManager() s3h := sssh.NewS3h(host, user, pwd, keyfile, cmd, printer, err_printer, mgr) s3h.SysLogin() }
func ParallelRun(config map[string]interface{}, raw_host_arr []string, start, end int, tmpdir string) error { host_arr := raw_host_arr[start:end] user, _ := config["User"].(string) pwd, _ := config["Password"].(string) keyfile, _ := config["Keyfile"].(string) cmd, _ := config["Cmd"].(string) args, _ := config["Args"].(string) timeout, _ := config["Timeout"].(int) cmd = format_cmd(cmd, args) printer, _ := config["Output"].(io.Writer) err_printer, _ := config["Errout"].(io.Writer) // Create master, the master is used to manage go routines mgr, _ := job.NewManager() // Setup tmp directory for tmp files dir := fmt.Sprintf("%s/.s3h.%d", tmpdir, time.Now().Nanosecond()) if err := os.Mkdir(dir, os.ModeDir|os.ModePerm); err != nil { return err } // Listen interrupt and kill signal, clear tmp files before exit. intqueue := make(chan os.Signal, 1) signal.Notify(intqueue, os.Interrupt, os.Kill) // If got interrupt or kill signal, delete tmp directory first, then exit with 1 go func() { <-intqueue os.RemoveAll(dir) os.Exit(1) }() // If the complete all the tasks normlly, stop listenning signals and remove tmp directory defer func() { signal.Stop(intqueue) os.RemoveAll(dir) }() // Create tmp file for every host, then executes. var tmpfiles []*os.File for _, h := range host_arr { file, _ := os.Create(fmt.Sprintf("%s/%s", dir, h)) err_file, _ := os.Create(fmt.Sprintf("%s/%s.err", dir, h)) tmpfiles = append(tmpfiles, file, err_file) s3h := sssh.NewS3h(h, user, pwd, keyfile, cmd, file, err_file, mgr) s3h.Timeout = timeout go s3h.Work() } // show realtime view for each host var dc *dircat.DirCat if terminal.IsTerminal(1) { wlist := []string{} for _, h := range host_arr { wlist = append(wlist, fmt.Sprintf("%s/%s", dir, h)) } dc, _ = dircat.Init(wlist...) go dc.Start() } // When a host is ready and request for continue, the master would echo CONTINUE for response to allow host to run size := len(host_arr) for { data, _ := mgr.Receive(-1) info, _ := data.(map[string]interface{}) if info["BODY"].(string) == "BEGIN" { mgr.Send(info["FROM"].(string), map[string]interface{}{"FROM": job.MASTER_ID, "BODY": "CONTINUE"}) } else if info["BODY"].(string) == "END" { // If master gets every hosts' END message, then it stop waiting. size -= 1 if size == 0 { break } } } if terminal.IsTerminal(1) { dc.Stop() } // close tmp files for _, f := range tmpfiles { f.Close() } // Merge all the hosts' output to the output file for _, h := range host_arr { report(os.Stderr, "", h, true) // copy err output first err_fn := fmt.Sprintf("%s/%s.err", dir, h) err_src, _ := os.Open(err_fn) io.Copy(err_printer, err_src) err_src.Close() // copy output then fn := fmt.Sprintf("%s/%s", dir, h) src, _ := os.Open(fn) io.Copy(printer, src) src.Close() // remove tmp file os.Remove(err_fn) os.Remove(fn) } return nil }
func ScpRun(config map[string]interface{}, host_arr []string) error { user, _ := config["User"].(string) pwd, _ := config["Password"].(string) keyfile, _ := config["Keyfile"].(string) timeout, _ := config["Timeout"].(int) src, _ := config["Source"].(string) dest, _ := config["Destdir"].(string) animation := make(chan int) animation_on := true go func() { fmt.Print("\033[?25l") b := []string{"-", "\\", "|", "/", "-", "|", "/"} i := 0 for { select { case <-animation: fmt.Print("\033[?25h") break case <-time.After(100 * time.Millisecond): i += 1 if animation_on { fmt.Printf("%v\r", b[i%7]) } } } }() perm := "0660" if fi, err := os.Stat(src); err != nil { return err } else { perm = fmt.Sprintf("%#o", fi.Mode()) } data, err := ioutil.ReadFile(src) if err != nil { return err } dest = dest + "/" + filepath.Base(src) // Create master, the master is used to manage go routines mgr, _ := job.NewManager() for _, h := range host_arr { scp := sssh.NewScp(h, user, pwd, keyfile, dest, perm, data, mgr) scp.Timeout = timeout go scp.Work() } // When a host is ready and request for continue, the master would echo CONTINUE for response to allow host to run size := len(host_arr) for { data, _ := mgr.Receive(-1) info, _ := data.(map[string]interface{}) if info["BODY"].(string) == "BEGIN" { mgr.Send(info["FROM"].(string), map[string]interface{}{"FROM": job.MASTER_ID, "BODY": "CONTINUE"}) } else if info["BODY"].(string) == "END" { // If master gets every hosts' END message, then it stop waiting. if animation_on { animation_on = false animation <- 0 } fmt.Print(info["RES"].(string)) size -= 1 if size == 0 { break } } } return nil }