func (c *Client) SFTPClient() (*sftp.Client, error) {
	return sftp.NewClient(c.SSHClient)
}
Return an sftp client. The client needs to be closed when it's no
longer needed.
package simplessh
import (
	"bytes"
	"fmt"
	"io"
	"io/ioutil"
	"net"
	"os"
	"os/user"
	"path/filepath"
	"sync"
	"time"
	"github.com/pkg/sftp"
	"golang.org/x/crypto/ssh"
)
const DefaultTimeout = 30 * time.Second
const sudoPwPrompt = "sudo_password"
var HostKeyCallback = ssh.InsecureIgnoreHostKey()
type sudoWriter struct {
	b     bytes.Buffer
	pw    string     
	stdin io.Writer  
	m     sync.Mutex
}
func (w *sudoWriter) Write(p []byte) (int, error) {
	if string(p) == sudoPwPrompt {
		w.stdin.Write([]byte(w.pw + "\n"))
		w.pw = ""  
		return len(p), nil
	}
	w.m.Lock()
	defer w.m.Unlock()
	return w.b.Write(p)
}
type Client struct {
	SSHClient *ssh.Client
}
func ConnectWithPassword(host, username, pass string) (*Client, error) {
	return ConnectWithPasswordTimeout(host, username, pass, DefaultTimeout)
}
func ConnectWithPasswordTimeout(host, username, pass string, timeout time.Duration) (*Client, error) {
	authMethod := ssh.Password(pass)
	return connect(username, host, authMethod, timeout)
}
func ConnectWithKeyFileTimeout(host, username, privKeyPath string, timeout time.Duration) (*Client, error) {
	if privKeyPath == "" {
		currentUser, err := user.Current()
		if err == nil {
			privKeyPath = filepath.Join(currentUser.HomeDir, ".ssh", "id_rsa")
		}
	}
	privKey, err := ioutil.ReadFile(privKeyPath)
	if err != nil {
		return nil, err
	}
	return ConnectWithKeyTimeout(host, username, string(privKey), timeout)
}
func ConnectWithKeyFile(host, username, privKeyPath string) (*Client, error) {
	return ConnectWithKeyFileTimeout(host, username, privKeyPath, DefaultTimeout)
}
func ConnectWithKeyTimeout(host, username, privKey string, timeout time.Duration) (*Client, error) {
	signer, err := ssh.ParsePrivateKey([]byte(privKey))
	if err != nil {
		return nil, err
	}
	authMethod := ssh.PublicKeys(signer)
	return connect(username, host, authMethod, timeout)
}
func ConnectWithKey(host, username, privKey string) (*Client, error) {
	return ConnectWithKeyTimeout(host, username, privKey, DefaultTimeout)
}
func ConnectWithAgentTimeout(host, username string, timeout time.Duration) (*Client, error) {
	return connectWithAgentTimeout(host, username, timeout)
}
func ConnectWithAgent(host, username string) (*Client, error) {
	return ConnectWithAgentTimeout(host, username, DefaultTimeout)
}
func connect(username, host string, authMethod ssh.AuthMethod, timeout time.Duration) (*Client, error) {
	if username == "" {
		user, err := user.Current()
		if err != nil {
			return nil, fmt.Errorf("Username wasn't specified and couldn't get current user: %v", err)
		}
		username = user.Username
	}
	config := &ssh.ClientConfig{
		User:            username,
		Auth:            []ssh.AuthMethod{authMethod},
		HostKeyCallback: HostKeyCallback,
	}
	host = addPortToHost(host)
	conn, err := net.DialTimeout("tcp", host, timeout)
	if err != nil {
		return nil, err
	}
	sshConn, chans, reqs, err := ssh.NewClientConn(conn, host, config)
	if err != nil {
		return nil, err
	}
	client := ssh.NewClient(sshConn, chans, reqs)
	c := &Client{SSHClient: client}
	return c, nil
}
func (c *Client) Exec(cmd string) ([]byte, error) {
	session, err := c.SSHClient.NewSession()
	if err != nil {
		return nil, err
	}
	defer session.Close()
	return session.CombinedOutput(cmd)
}
func (c *Client) ExecSudo(cmd, passwd string) ([]byte, error) {
	session, err := c.SSHClient.NewSession()
	if err != nil {
		return nil, err
	}
	defer session.Close()
	cmd = "sudo -p " + sudoPwPrompt + " -S " + cmd
	w := &sudoWriter{
		pw: passwd,
	}
	w.stdin, err = session.StdinPipe()
	if err != nil {
		return nil, err
	}
	session.Stdout = w
	session.Stderr = w
	err = session.Run(cmd)
	return w.b.Bytes(), err
}
func (c *Client) Download(remote, local string) error {
	client, err := sftp.NewClient(c.SSHClient)
	if err != nil {
		return err
	}
	defer client.Close()
	remoteFile, err := client.Open(remote)
	if err != nil {
		return err
	}
	defer remoteFile.Close()
	localFile, err := os.Create(local)
	if err != nil {
		return err
	}
	defer localFile.Close()
	_, err = io.Copy(localFile, remoteFile)
	return err
}
func (c *Client) Upload(local, remote string) error {
	client, err := sftp.NewClient(c.SSHClient)
	if err != nil {
		return err
	}
	defer client.Close()
	localFile, err := os.Open(local)
	if err != nil {
		return err
	}
	defer localFile.Close()
	remoteFile, err := client.Create(remote)
	if err != nil {
		return err
	}
	_, err = io.Copy(remoteFile, localFile)
	return err
}
func (c *Client) Remove(path string) error {
	client, err := sftp.NewClient(c.SSHClient)
	if err != nil {
		return err
	}
	defer client.Close()
	return client.Remove(path)
}
func (c *Client) RemoveDirectory(path string) error {
	client, err := sftp.NewClient(c.SSHClient)
	if err != nil {
		return err
	}
	defer client.Close()
	return client.RemoveDirectory(path)
}
func (c *Client) ReadAll(filepath string) ([]byte, error) {
	sftp, err := c.SFTPClient()
	if err != nil {
		panic(err)
	}
	defer sftp.Close()
	file, err := sftp.Open(filepath)
	if err != nil {
		return nil, err
	}
	defer file.Close()
	return ioutil.ReadAll(file)
}
func (c *Client) Close() error {
	return c.SSHClient.Close()
}