func (p *Jobs) runCmd(i int, cmd string, client *ssh.Client, outfile *os.File) { session, err := client.NewSession() if err != nil { log.Fatal("Failed to create SSH session to server [" + p.Servers[i] + "] with error: " + err.Error()) } defer session.Close() session.Stdout = outfile session.Stderr = outfile // Set up terminal modes modes := ssh.TerminalModes{ ssh.ECHO: 0, // disable echoing ssh.TTY_OP_ISPEED: 14400, // input speed = 14.4kbaud ssh.TTY_OP_OSPEED: 14400, // output speed = 14.4kbaud } // Request pseudo terminal if err := session.RequestPty("xterm", 80, 40, modes); err != nil { log.Fatalf("request for pseudo terminal failed: %s", err) } err = session.Start(cmd) if err != nil { log.Fatal("run command ["+cmd+"] on server ("+p.Servers[i]+") failed with -> ", err) } err = session.Wait() // TODO: make cmd not longer than 80 if err == nil { log.Printf("[%15s] %-80s %s%s%s", p.Servers[i], cmd, CLR_G, "√", CLR_N) } else { log.Printf("[%15s] %-80s %s%s%s", p.Servers[i], cmd, CLR_R, "✗", CLR_N) } }
//transfer a directory to remote host,with single tcp and tar.gz format //Stdout will be ignore. //Stderr will treat as an error from remote command func CopyDirectory(client *ssh.Client, selfPath string, remotePath string) (err error) { session, err := client.NewSession() if err != nil { return fmt.Errorf("[CopyDirectory]Failed to create session: %s", err.Error()) } defer session.Close() w, err := session.StdinPipe() if err != nil { return } defer w.Close() errBuf := &bytes.Buffer{} session.Stderr = errBuf escapedRemotePath := kmgCmd.BashEscape(remotePath) err = session.Start(fmt.Sprintf("mkdir -p %s;tar -xz -C %s", escapedRemotePath, escapedRemotePath)) if err != nil { return fmt.Errorf("[CopyDirectory] Failed to Run: %s", err.Error()) } err = kmgTar.PackageDirectoryTarGz(selfPath, w) if err != nil { return } err = w.Close() if err != nil { return } err = session.Wait() if err != nil { return fmt.Errorf("[CopyDirectory] session.Wait() err:%s", err.Error()) } if errBuf.Len() != 0 { return fmt.Errorf("[CopyDirectory] remote: %s", string(errBuf.Bytes())) } return nil }
// New creates a new SFTP client on conn. func NewClient(conn *ssh.Client) (*Client, error) { s, err := conn.NewSession() if err != nil { return nil, err } if err := s.RequestSubsystem("sftp"); err != nil { return nil, err } pw, err := s.StdinPipe() if err != nil { return nil, err } pr, err := s.StdoutPipe() if err != nil { return nil, err } sftp := &Client{ w: pw, r: pr, } if err := sftp.sendInit(); err != nil { return nil, err } return sftp, sftp.recvVersion() }
func cmdExecRemote(sshc *ssh.Client, args ...string) { cmd := strings.Join(args, " ") log.Printf("Executing (remotely) %s", cmd) if DUMMY { return } sshs, err := sshc.NewSession() if err != nil { log.Fatalf("Could not create ssh session: %v", err) } defer sshs.Close() stdout, err := sshs.StdoutPipe() if err != nil { log.Fatalf("Could not get stdout of ssh session: %v", err) } stderr, err := sshs.StderrPipe() if err != nil { log.Fatalf("Could not get stderr of ssh session: %v", err) } err = sshs.Start(cmd) if err != nil { log.Fatalf("Could not execute command: %v", err) } go io.Copy(os.Stdout, stdout) go io.Copy(os.Stderr, stderr) err = sshs.Wait() if err != nil { log.Fatalf("Error executing (remote) command: %v", err) } }
func combined(c *ssh.Client, cmd string) ([]byte, error) { s, err := c.NewSession() if err != nil { return nil, err } defer s.Close() return s.CombinedOutput(cmd) }
//transfer a file to remote host,with single tcp and gz format //Stdout will be ignore. //Stderr will treat as an error from remote command //TODO test func CopyFile(client *ssh.Client, selfPath string, remotePath string) (err error) { session, err := client.NewSession() if err != nil { return fmt.Errorf("[CopyFile]Failed to create session: %s", err.Error()) } defer session.Close() w, err := session.StdinPipe() if err != nil { return } defer w.Close() errReader, err := session.StderrPipe() if err != nil { return } escapedRemotePath := kmgCmd.BashEscape(remotePath) escapedRemoteDir := kmgCmd.BashEscape(path.Dir(remotePath)) err = session.Start(fmt.Sprintf("mkdir -p %s;cat > %s", escapedRemoteDir, escapedRemotePath)) if err != nil { return fmt.Errorf("[CopyFile] Failed to Start: %s", err.Error()) } f, err := os.Open(selfPath) if err != nil { return } defer f.Close() //gzipW := gzip.NewWriter(w) //defer gzipW.Close() _, err = io.Copy(w, f) if err != nil { return fmt.Errorf("[CopyFile] io.Copy: %s", err) } //err = gzipW.Close() //if err!=nil{ // return //} err = w.Close() if err != nil { return } errBytes, err := ioutil.ReadAll(errReader) if err != nil { return } if len(errBytes) != 0 { return fmt.Errorf("[CopyFile] remote: %s", string(errBytes)) } err = session.Wait() if err != nil { return fmt.Errorf("[CopyFile] session.Wait() err:%s", err.Error()) } return nil }
func (v *vm) Run(command string, attempts attempt.Strategy, out io.Writer, stderr io.Writer) error { var sc *ssh.Client err := attempts.Run(func() (err error) { fmt.Fprintf(stderr, "Attempting to ssh to %s:22...\n", v.IP()) sc, err = v.DialSSH() return }) if err != nil { return err } defer sc.Close() sess, err := sc.NewSession() sess.Stdin = bytes.NewBufferString(command) sess.Stdout = out sess.Stderr = stderr if err := sess.Run("bash"); err != nil { return fmt.Errorf("failed to run command on %s: %s", v.IP(), err) } return nil }
func copyFile(c *ssh.Client, r io.Reader, path string) error { s, err := c.NewSession() if err != nil { return err } defer s.Close() w, err := s.StdinPipe() if err != nil { return err } s.Start("tee " + path) _, err = io.Copy(w, r) if err != nil { return err } w.Close() return s.Wait() }
//run sudo a command in remote and ask password in current console, //Stdout will goto current console too. //Stderr will treat as an error from remote command func SudoCommand(client *ssh.Client, cmd string) (err error) { session, err := client.NewSession() if err != nil { return fmt.Errorf("[SudoCommand] Failed to create session: %s", err.Error()) } defer session.Close() w, err := session.StdinPipe() if err != nil { return } session.Stdout = os.Stdout errBuf := &bytes.Buffer{} session.Stderr = errBuf // Set up terminal modes modes := ssh.TerminalModes{ ssh.ECHO: 0, // disable echoing ssh.TTY_OP_ISPEED: 14400, // input speed = 14.4kbaud ssh.TTY_OP_OSPEED: 14400, // output speed = 14.4kbaud } // Request pseudo terminal if err := session.RequestPty("xterm", 80, 40, modes); err != nil { return fmt.Errorf("[SudoCommand] request for pseudo terminal failed: %s", err) } err = session.Start(cmd) if err != nil { return fmt.Errorf("[SudoCommand] Failed to Start: %s", err.Error()) } pass := gopass.GetPasswd() w.Write(append(pass, byte('\n'))) err = session.Wait() if err != nil { return fmt.Errorf("[SudoCommand] session.Wait err: %s", err.Error()) } if errBuf.Len() != 0 { return fmt.Errorf("[SudoCommand] remote err: %s", err.Error()) } return nil }
func createPipeNet(client *ssh.Client, cmd string) (pn *PipeNet, err error) { session, err := client.NewSession() if err != nil { return } pn = &PipeNet{ wa: session, c: client, name: "ssh", } pn.w, err = session.StdinPipe() if err != nil { return } pn.r, err = session.StdoutPipe() if err != nil { return } err = session.Start(cmd) return }