This is a creation in Article, where the information may have evolved or changed.
Busy with the small program, on the window to the Linux machine mass command,
The writing is not good welcome everyone to correct, there is the use of this tool to send malicious commands, please leave,
Compiled a copy of the 64_window and Linux programs for your reference, Rm_tmp_cmd.exe under win to provide use!
My directory structure:
Flagparse
--------Flag.go
Getconf
--------Getconfig.go
Maste
--------Scp.go
--------Ssh_client.go
Zip_file
--------Zip.go
Maste.go
Ssh.conf
Command file: ssh.conf The first line is the need to mass the command, in English ', ' separated and then the following is the host ip:port user password command----> commands are issued only to this host, will not be sent to the other host, Can be understood as private command 0 ' ls-a,df-h1 ' 127.0.0.1:5000 ' root ' 123456 ' ls-l,free-m2 ' 127.0.0.1:5000 ' root ' 123456 ' df-h,pwd3 ' 127.0.0.1:5506 ' root ' 123456 ' cd/mnt/&& python ping.py > 2015.txt &
Flag.go command Line parsing parameter file: Package Flagparseimport ("flag") Func flag () (*string, *bool, *string, *bool) {var (sendfile = flag). String ("F", "", "this parameter indicates that a file is sent to all label hosts, the parameter represents a file path, for example:-f=/mnt/2015.go") Global_command = flag. Bool ("G", False, "This parameter represents whether the global command is executed, is not enabled by default, if enabled using:-g=true or-G") Sendall = flag. String ("S", "", "this parameter represents the Send command to the host of these labels:-s=1,2 executes the label command") printlog = flag. Bool ("P", False, "This parameter defaults to whether printing output execution results if the print log uses:-P =true or-P")) flag. Parse () return sendfile, Global_command, Sendall, Printlog}
Getconfig.go parsing profile (ssh.conf) package Getconfimport ("Bufio" "FMT" "IO" "OS" "Path/filepath" "strings")// Gets the ssh.conf configuration file that returns the data per row in the form of a map to Func getconfig () map[string][]string {propath: = os. Args[0]os. Chdir (filepath. Dir (Propath)) Config: = Make (map[string][]string) File, err: = OS. Open ("ssh.conf") if err! = Nil {fmt. Println ("From GetConfig:", err)}defer file.close () Buf: = Bufio. Newreader (File) for {line, _, Err: = Buf.readline () if err! = Nil {if Err = = Io. EOF {break}fmt. Println ("From GetConfig:", err) break}x: = Strings. Split (String (line), "'") config[x[0]] = X[1:]}return Config}
Scp.go is used to send files: Package Masteimport ("Zip_file" "FMT" "Go-ssh/ssh" "IO" "OS" "Path/filepath" "strings") Func Use_scp_send ( Sendall, Path *string, config map[string][]string, Ok, Err, Sta Chan string) {flaglist: = strings. Split (*sendall, ",") Name: = FilePath. Base (*path) Sendfilepath: = *patholdpath, _: = OS. GETWD () If File, e: = os. Stat (Sendfilepath); E = = Nil {if File.isdir () {zip_file.addfilestozip (Sendfilepath, Name) Sendfilepath = FMT. Sprintf ("%s\\%s.zip", OldPath, name) name = FMT. Sprintf ("%s.zip", Name)}} else {fmt. Println (Sendfilepath, ": Not present!") Os. Exit (2)}fmt. PRINTLN ("Sent file name:", name) if *sendall = = "" {For I, _: = Range Config {if I! = "0" {Go connect (config[i][0], config[i][1], C Onfig[i][2], Sendfilepath, Name, Ok, ERR, Sta)}}, else {for _, I: = Range flaglist {Go connect (config[i][0], config[i][1], Config[i][2], Sendfilepath, Name, OK, err, STA)}}}func connect (IP, user, password, FilePath, Name string, Ok, err, STA ch An string) {Auth: = []ssh. Authmethod{ssh. Password (Password)}conf: = ssh. ClienTconfig{auth:auth, user:user}client, err0: = ssh. Dial ("tcp", IP, &conf) if err0 = = Nil {OK <-fmt. Sprint (IP, "Connection status: OK")} else {Err <-fmt. Sprint (IP, "Connection error:", err0)}defer Client.close () conn, err1: = Client.newsession () If err1 = nil {Ok <-fmt. Sprint (IP, "session state: OK")} else {Err <-fmt. Sprint (IP, "Session error:", ERR1)}defer Conn. Close () go func () {Buf: = make ([]byte, 1024x768) W, _: = conn. Stdinpipe () defer w.close () File, _: = OS. Open (FilePath) defer file.close () info, _: = File.stat () fmt. Fprintln (W, "C0644", info. Size (), Name) for {n, err: = File.read (Buf) fmt. Fprint (W, String (buf[:n))) If err! = Nil {if Err = = Io. EOF {return} else {panic (err)}}}} () ERR3: = conn. Run ("scp-qrt/mnt/")//will be saved under MNT if Err3. Error () = = "Process exited with:1. Reason was: ()" {OK <-fmt. Sprint (IP, "execution status: OK") Sta <-"OK"} else {ERR <-fmt. Sprint (IP, "execution error:", ERR3)}}
Ssh_client.go Connecting host Main program package Masteimport ( "bytes" "FMT" " Go-ssh/ssh ") Func ssh_client (ip_port, user, password string, command []string, P bool, Ok, ERR, Res Chan string) {&NBSP;&NB Sp &NBSP;PASSWD: = []ssh. Authmethod{ssh. Password (Password)} conf: = ssh. Clientconfig{user:user, auth:passwd} client, err: = ssh. Dial ("TCP", Ip_port, &conf) if err = = Nil { ok <-fmt. Sprint (Ip_port, " Connection Status: OK") } else { err <-fmt. Sprint (Ip_port, " errorinfo:", err) return } defer client.close () for _, Command: = Range Command { &nbs P;if session, Err: = Client.newsession (); Err = = Nil { defer session. Close () &NBSP;&NBsp var Result bytes. buffer session. Stderr = &Result session. Stdout = &Result err = session. Run (Command) if err = = Nil { & nbsp; ok <-fmt. Sprint (ip_port, " Command:", command, " Execution Status: OK") } else { err <-fmt. Sprint (Ip_port, " errorinfo:", err) } if P { res <-FMT. Sprint (Ip_port, " execution result \ n", result.string ()) &Nbsp; } } }}
Zip.go call this function to compress the package zip_fileimport ("Archive/zip" "FMT" "IO" "OS" "Path/filepath"//"strings") func before using the Send file Addfilestozip (Path, Name string) {//var PathName stringfile, _: = OS. Create (FMT. Sprintf ("%s.zip", Name))/*ps: = Strings. Split (Path, "/") If Len (PS) = = 2 {PathName = FMT. Sprintf ("%s/", Ps[0])} else {PathName = strings. Join (Ps[:len (PS)-1], "/")}os. Chdir (PathName) Path = Ps[len (PS) -1]*/os. Chdir (filepath. Dir (path) path = filepath. Base (Path) defer file.close () Zip: = zip. Newwriter (File) defer zip.close () Walk: = Func (Path string, info os. FileInfo, err Error) error {if Err! = Nil {fmt. PRINTLN (ERR) return err}if info. Isdir () {return NIL}SRC, _: = OS. Open (Path) defer src.close () H: = &zip. Fileheader{name:path, Method:zip. Deflate, Flags:0x800}filename, _: = Zip.createheader (h) Io. Copy (FileName, SRC) Zip.flush () return Nil}filepath. Walk (Path, Walk)}
Maste.go Entry Package Mainimport ("getconf" "Maste" "Flagparse" "FMT" "OS" "Os/exec" "Path/filepath" "Strings" "Time") var Rm_cmd_path, _ = os. GETWD () var (timeout int = 0TimeOut int = 10Ok Chan string = Make (Chan string) Err chan string = ma Ke (chan string) Res chan string = Make (Chan string) Sta chan string = Make (Chan string)) Func main () {var Num intsend File, Global_command, Sendall, Printlog: = Flagparse. Flag () Config: = Getconf.getconfig () if *sendfile! = "" {TimeOut = 3600maste.use_scp_send (Sendall, Sendfile, config, Ok, ERR , Sta)} else {SendCommand (Sendall, Global_command, Printlog, config)}if *sendall = = "" {num = Len (config)-1} else {num = Len (Strings. Split (*sendall, ","))}defer Rmfile (Sendfile) for {check_status (*printlog, Num, Sendfile)}}//send commands based on parameters func SendCommand ( Sendall *string, Global_command, printlog *bool, config map[string][]string) {flaglist: = strings. Split (*sendall, ",") if *sendall = = "" {for _, I: = Range Flaglist {Com: = Global_cmd (config["0"]) goMaste.ssh_client (Config[i][0], config[i][1], config[i][2], Com, *printlog, Ok, ERR, Res)}} else {for _, I: = Range Flaglis t {Com: = Private_cmd (config["0"], config[i][3], *global_command) go maste.ssh_client (config[i][0], config[i][1], Config[i][2], Com, *printlog, Ok, ERR, Res)}}}//parse the command field in ssh.conf: Func global_cmd (Global []string) []string {return] Strings. Split (Global[0], ",")}func private_cmd (Global []string, Private string, globlcomand bool) []string {if Globlcomand {Priva Te_cmd: = Strings. Split (Private, ",") var cmd []string = Global_cmd (Global) For _, I: = Range private_cmd {cmd = append (cmd, i)}return cmd} el SE {return strings. Split (Private, ",")}}//gets the status of Chan pipeline. Func check_status (p bool, Num int, Sendfile *string) {var break int = 0if P {for {Selec t {case x: = <-err:fmt. PRINTLN (x) timeout = timeout-2case y: = <-ok:fmt. Println (y) timeout = 0case Z: = <-res:fmt. Println (z) timeout = 0case <-sta:break = break + 1if break >= Num {rmfile (Sendfile) OS. Exit (1)}default:if TiMeout > TimeOut {os. Exit (2)}timeout = timeout + 1time. Sleep (1E9)}}} else {for {select {case x: = <-err:fmt. PRINTLN (x) timeout = timeout-2case y: = <-ok:fmt. Println (y) timeout = 0case <-sta:break = break + 1if break >= Num {rmfile (Sendfile) OS. Exit (3)}default:if Timeout > timeout {os. Exit (4)}timeout = timeout + 1time. Sleep (1e9)}}}}func rmfile (Sendfile *string) {os. Chdir (Rm_cmd_path) if info, err: = OS. Stat (*sendfile); Err = = Nil && info. Isdir () {rm_path: = FMT. Sprintf ("%s.zip", filepath. Base (*sendfile)) cmd: = Exec.command ("Rm_tmp_cmd.exe", Rm_path) cmd. Run ()}}