sftp传文件到远程服务器,go语言实现sftp包上传文件和文件夹到远程服务器操作...

使用go语言的第三方包:github.com/pkg/sftp和golang.org/x/crypto/ssh实现文件和文件夹传输。

1、创建connect方法:

func connect(user, password, host string, port int) (*sftp.Client, error) {

var (

auth []ssh.AuthMethod

addr string

clientConfig *ssh.ClientConfig

sshClient *ssh.Client

sftpClient *sftp.Client

err error

)

// get auth method

auth = make([]ssh.AuthMethod, 0)

auth = append(auth, ssh.Password(password))

clientConfig = &ssh.ClientConfig{

User: user,

Auth: auth,

Timeout: 30 * time.Second,

HostKeyCallback: ssh.InsecureIgnoreHostKey(), //ssh.FixedHostKey(hostKey),

}

// connet to ssh

addr = fmt.Sprintf("%s:%d", host, port)

if sshClient, err = ssh.Dial("tcp", addr, clientConfig); err != nil {

return nil, err

}

// create sftp client

if sftpClient, err = sftp.NewClient(sshClient); err != nil {

return nil, err

}

return sftpClient, nil

}

2、上传文件

func uploadFile(sftpClient *sftp.Client, localFilePath string, remotePath string) {

srcFile, err := os.Open(localFilePath)

if err != nil {

fmt.Println("os.Open error : ", localFilePath)

log.Fatal(err)

}

defer srcFile.Close()

var remoteFileName = path.Base(localFilePath)

dstFile, err := sftpClient.Create(path.Join(remotePath, remoteFileName))

if err != nil {

fmt.Println("sftpClient.Create error : ", path.Join(remotePath, remoteFileName))

log.Fatal(err)

}

defer dstFile.Close()

ff, err := ioutil.ReadAll(srcFile)

if err != nil {

fmt.Println("ReadAll error : ", localFilePath)

log.Fatal(err)

}

dstFile.Write(ff)

fmt.Println(localFilePath + " copy file to remote server finished!")

}

3、上传文件夹

func uploadDirectory(sftpClient *sftp.Client, localPath string, remotePath string) {

localFiles, err := ioutil.ReadDir(localPath)

if err != nil {

log.Fatal("read dir list fail ", err)

}

for _, backupDir := range localFiles {

localFilePath := path.Join(localPath, backupDir.Name())

remoteFilePath := path.Join(remotePath, backupDir.Name())

if backupDir.IsDir() {

sftpClient.Mkdir(remoteFilePath)

uploadDirectory(sftpClient, localFilePath, remoteFilePath)

} else {

uploadFile(sftpClient, path.Join(localPath, backupDir.Name()), remotePath)

}

}

fmt.Println(localPath + " copy directory to remote server finished!")

}

4、上传测试

func DoBackup(host string, port int, userName string, password string, localPath string, remotePath string) {

var (

err error

sftpClient *sftp.Client

)

start := time.Now()

sftpClient, err = connect(userName, password, host, port)

if err != nil {

log.Fatal(err)

}

defer sftpClient.Close()

_, errStat := sftpClient.Stat(remotePath)

if errStat != nil {

log.Fatal(remotePath + " remote path not exists!")

}

backupDirs, err := ioutil.ReadDir(localPath)

if err != nil {

log.Fatal(localPath + " local path not exists!")

}

uploadDirectory(sftpClient, localPath, remotePath)

elapsed := time.Since(start)

fmt.Println("elapsed time : ", elapsed)

}

补充:go实现ssh远程机器并传输文件

核心依赖包:

golang.org/x/crypto/ssh

github.com/pkg/sftp

其中golang.org/x/crypto/ssh 可从github上下载,

ssh连接源码(这里是根据秘钥连接):

var keypath = "key/id_rsa"

//获取秘钥

func publicKey(path string) ssh.AuthMethod {

keypath, err := homedir.Expand(path)

if err != nil {

fmt.Println("获取秘钥路径失败", err)

}

key, err1 := ioutil.ReadFile(keypath)

if err1 != nil {

fmt.Println("读取秘钥失败", err1)

}

signer, err2 := ssh.ParsePrivateKey(key)

if err2 != nil {

fmt.Println("ssh 秘钥签名失败", err2)

}

return ssh.PublicKeys(signer)

}

//获取ssh连接

func GetSSHConect(ip, user string, port int) (*ssh.Client) {

con := &ssh.ClientConfig{

User: user,

Auth: []ssh.AuthMethod{publicKey(keypath)},

HostKeyCallback: func(hostname string, remote net.Addr, key ssh.PublicKey) error {

return nil

},

}

addr := fmt.Sprintf("%s:%d", ip, port)

client, err := ssh.Dial("tcp", addr, con)

if err != nil {

fmt.Println("Dail failed: ", err)

panic(err)

}

return client

}

// 远程执行脚本

func Exec_Task(ip, user, localpath, remotepath string) int {

port := 22

client := GetSSHConect(ip, user, port)

UploadFile(ip, user, localpath, remotepath, port)

session, err := client.NewSession()

if err != nil {

fmt.Println("创建会话失败", err)

panic(err)

}

defer session.Close()

remoteFileName := path.Base(localpath)

dstFile := path.Join(remotepath, remoteFileName)

err1 := session.Run(fmt.Sprintf("/usr/bin/sh %s", dstFile))

if err1 != nil {

fmt.Println("远程执行脚本失败", err1)

return 2

} else {

fmt.Println("远程执行脚本成功")

return 1

}

}

文件传输功能:

//获取ftp连接

func getftpclient(client *ssh.Client) (*sftp.Client) {

ftpclient, err := sftp.NewClient(client)

if err != nil {

fmt.Println("创建ftp客户端失败", err)

panic(err)

}

return ftpclient

}

//上传文件

func UploadFile(ip, user, localpath, remotepath string, port int) {

client := GetSSHConect(ip, user, port)

ftpclient := getftpclient(client)

defer ftpclient.Close()

remoteFileName := path.Base(localpath)

fmt.Println(localpath, remoteFileName)

srcFile, err := os.Open(localpath)

if err != nil {

fmt.Println("打开文件失败", err)

panic(err)

}

defer srcFile.Close()

dstFile, e := ftpclient.Create(path.Join(remotepath, remoteFileName))

if e != nil {

fmt.Println("创建文件失败", e)

panic(e)

}

defer dstFile.Close()

buffer := make([]byte, 1024)

for {

n, err := srcFile.Read(buffer)

if err != nil {

if err == io.EOF {

fmt.Println("已读取到文件末尾")

break

} else {

fmt.Println("读取文件出错", err)

panic(err)

}

}

dstFile.Write(buffer[:n])

//注意,由于文件大小不定,不可直接使用buffer,否则会在文件末尾重复写入,以填充1024的整数倍

}

fmt.Println("文件上传成功")

}

//文件下载

func DownLoad(ip, user, localpath, remotepath string, port int) {

client := GetSSHConect(ip, user, port)

ftpClient := getftpclient(client)

defer ftpClient.Close()

srcFile, err := ftpClient.Open(remotepath)

if err != nil {

fmt.Println("文件读取失败", err)

panic(err)

}

defer srcFile.Close()

localFilename := path.Base(remotepath)

dstFile, e := os.Create(path.Join(localpath, localFilename))

if e != nil {

fmt.Println("文件创建失败", e)

panic(e)

}

defer dstFile.Close()

if _, err1 := srcFile.WriteTo(dstFile); err1 != nil {

fmt.Println("文件写入失败", err1)

panic(err1)

}

fmt.Println("文件下载成功")

}

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。如有错误或未考虑完全的地方,望不吝赐教。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值