// New creates a new SFTP client on conn. func NewClient(conn *ssh.ClientConn) (*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() }
//TODO Do not return string, also return error func Execute(client *ssh.ClientConn, command string) string { // Each ClientConn can support multiple interactive sessions, // represented by a Session. defer client.Close() // Create a session session, err := client.NewSession() if err != nil { log.Fatalf("unable to create session: %s", err) } defer session.Close() // Set up terminal modes modes := ssh.TerminalModes{ ECHO: 0, // disable echoing TTY_OP_ISPEED: 14400, // input speed = 14.4kbaud 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) } var b bytes.Buffer session.Stdout = &b if err := session.Run(command); err != nil { session.Stderr = &b //return "\033[31mError: '" + command + "' failed to run\033[0m \n" } return ("\033[31m" + b.String() + "\033[0m") }
func startChan(conn *ssh.ClientConn, wg *sync.WaitGroup) { defer wg.Done() ch, err := conn.NewSession() if err != nil { log.Printf("unable to open session: %v", err) return } defer ch.Close() stdin, err := ch.StdinPipe() if err != nil { log.Printf("unable to open stdin: %v", err) return } stdout, err := ch.StdoutPipe() if err != nil { log.Printf("unable to open stdout: %v", err) return } shuffle <- stdout if err := ch.Start("cat"); err != nil { log.Printf("unable to start command: %v", err) return } defer ch.Wait() // prime the pump if _, err := stdin.Write(make([]byte, 37000)); err != nil { log.Printf("unable to write: %v", err) return } _, err = io.Copy(stdin, <-shuffle) log.Println(err) }
func Run(conn *ssh.ClientConn, cmd string) (string, error) { log.Println("[ssh]", "[run]", cmd) session, err := conn.NewSession() if err != nil { return "", err } defer session.Close() if strings.HasPrefix(cmd, "sudo") { err = session.RequestPty("xterm", 40, 80, ssh.TerminalModes{}) if err != nil { return "", err } } bs, err := session.CombinedOutput(cmd) return string(bs), err }
func SendFile(conn *ssh.ClientConn, local, remote string) error { session, err := conn.NewSession() if err != nil { return err } defer session.Close() session.Stdout = os.Stdout session.Stderr = os.Stderr f, err := os.Open(local) if err != nil { return err } defer f.Close() info, err := f.Stat() if err != nil { return err } hold := make(chan bool) done := make(chan error) go func() { w, err := session.StdinPipe() if err != nil { done <- err return } defer w.Close() ww := tar.NewWriter(w) defer ww.Close() hold <- true hdr, err := tar.FileInfoHeader(info, "/"+path.Base(remote)) if err != nil { done <- err return } hdr.Name = path.Base(remote) err = ww.WriteHeader(hdr) if err != nil { done <- err return } _, err = io.Copy(ww, f) if err != nil { done <- err return } }() <-hold go func() { log.Println("[ssh] [send-file]", local, "to", remote) done <- session.Run("mkdir -p " + path.Dir(cleanName(remote)) + " && tar -m -C " + path.Dir(cleanName(remote)) + " -x") }() return <-done }