go語(yǔ)言實(shí)現(xiàn)sftp包上傳文件和文件夾到遠(yuǎn)程服務(wù)器操作
使用go語(yǔ)言的第三方包:github.com/pkg/sftp和golang.org/x/crypto/ssh實(shí)現(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、上傳測(cè)試
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)
}
補(bǔ)充:go實(shí)現(xiàn)ssh遠(yuǎn)程機(jī)器并傳輸文件
核心依賴包:
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
}
// 遠(yuǎn)程執(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)建會(huì)話失敗", 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("遠(yuǎn)程執(zhí)行腳本失敗", err1)
return 2
} else {
fmt.Println("遠(yuǎn)程執(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("讀取文件出錯(cuò)", err)
panic(err)
}
}
dstFile.Write(buffer[:n])
//注意,由于文件大小不定,不可直接使用buffer,否則會(huì)在文件末尾重復(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("文件下載成功")
}
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教。
- Java連接sftp服務(wù)器實(shí)現(xiàn)上傳下載功能
- Java連接服務(wù)器的兩種方式SFTP和FTP
- Windows?10搭建SFTP服務(wù)器的詳細(xì)過程【公網(wǎng)遠(yuǎn)程訪問】
- PyCharm如何配置SSH和SFTP連接遠(yuǎn)程服務(wù)器
- 詳解Java使用Jsch與sftp服務(wù)器實(shí)現(xiàn)ssh免密登錄
- java使用SFTP上傳文件到資源服務(wù)器
- Java使用SFTP上傳文件到服務(wù)器的簡(jiǎn)單使用
- Shell腳本搭建FTP服務(wù)器(vsftpd)
- 開源SFTP服務(wù)器軟件SFTPGo詳解
相關(guān)文章
Go基本數(shù)據(jù)類型與string類型互轉(zhuǎn)
本文主要介紹了Go基本數(shù)據(jù)類型與string類型互轉(zhuǎn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-03-03
使用Go語(yǔ)言編寫一個(gè)極簡(jiǎn)版的容器Container
Docker作為一種流行的容器化技術(shù),對(duì)于每一個(gè)程序開發(fā)者而言都具有重要性和必要性,因?yàn)槿萜骰嚓P(guān)技術(shù)的普及大大簡(jiǎn)化了開發(fā)環(huán)境配置、更好的隔離性和更高的安全性,對(duì)于部署項(xiàng)目和團(tuán)隊(duì)協(xié)作而言也更加方便,本文將嘗試使用Go語(yǔ)言編寫一個(gè)極簡(jiǎn)版的容器2023-10-10
關(guān)于golang?struct?中的?slice?無(wú)法原子賦值的問題
這篇文章主要介紹了為什么?golang?struct?中的?slice?無(wú)法原子賦值的問題,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2024-01-01
gin框架Context如何獲取Get?Query?Param函數(shù)數(shù)據(jù)
這篇文章主要為大家介紹了gin框架Context?Get?Query?Param函數(shù)獲取數(shù)據(jù),有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-03-03
MacOS中 VSCode 安裝 GO 插件失敗問題的快速解決方法
這篇文章主要介紹了MacOS中 VSCode 安裝 GO 插件失敗問題的快速解決方法,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-05-05
golang復(fù)用http.request.body的方法示例
這篇文章主要給大家介紹了關(guān)于golang復(fù)用http.request.body的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2018-10-10
go-zero數(shù)據(jù)的流處理利器fx使用詳解
這篇文章主要為大家介紹了go-zero數(shù)據(jù)的流處理利器fx使用詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-05-05

