go語言實現(xiàn)sftp包上傳文件和文件夾到遠程服務(wù)器操作
使用go語言的第三方包:github.com/pkg/sftp和golang.org/x/crypto/ssh實現(xiàn)文件和文件夾傳輸。
1、創(chuàng)建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實現(xiàn)ssh遠程機器并傳輸文件
核心依賴包:
golang.org/x/crypto/ssh
github.com/pkg/sftp
其中g(shù)olang.org/x/crypto/ssh 可從github上下載,
下載地址:https://github.com/golang/crypto
ssh連接源碼(這里是根據(jù)秘鑰連接):
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 } // 遠程執(zhí)行腳本 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("創(chuàng)建會話失敗", 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("遠程執(zhí)行腳本失敗", err1) return 2 } else { fmt.Println("遠程執(zhí)行腳本成功") return 1 } }
文件傳輸功能:
//獲取ftp連接 func getftpclient(client *ssh.Client) (*sftp.Client) { ftpclient, err := sftp.NewClient(client) if err != nil { fmt.Println("創(chuàng)建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("創(chuàng)建文件失敗", 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,否則會在文件末尾重復(fù)寫入,以填充1024的整數(shù)倍 } 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("文件創(chuàng)建失敗", e) panic(e) } defer dstFile.Close() if _, err1 := srcFile.WriteTo(dstFile); err1 != nil { fmt.Println("文件寫入失敗", err1) panic(err1) } fmt.Println("文件下載成功") }
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。如有錯誤或未考慮完全的地方,望不吝賜教。
相關(guān)文章
Go基本數(shù)據(jù)類型與string類型互轉(zhuǎn)
本文主要介紹了Go基本數(shù)據(jù)類型與string類型互轉(zhuǎn),文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-03-03關(guān)于golang?struct?中的?slice?無法原子賦值的問題
這篇文章主要介紹了為什么?golang?struct?中的?slice?無法原子賦值的問題,本文給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2024-01-01gin框架Context如何獲取Get?Query?Param函數(shù)數(shù)據(jù)
這篇文章主要為大家介紹了gin框架Context?Get?Query?Param函數(shù)獲取數(shù)據(jù),有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-03-03MacOS中 VSCode 安裝 GO 插件失敗問題的快速解決方法
這篇文章主要介紹了MacOS中 VSCode 安裝 GO 插件失敗問題的快速解決方法,本文給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-05-05golang復(fù)用http.request.body的方法示例
這篇文章主要給大家介紹了關(guān)于golang復(fù)用http.request.body的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2018-10-10go-zero數(shù)據(jù)的流處理利器fx使用詳解
這篇文章主要為大家介紹了go-zero數(shù)據(jù)的流處理利器fx使用詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-05-05