go语言实现sftp包上传文件和文件夹到远程服务器操作
作者:奔流入海 发布时间:2024-05-08 10:22:18
标签: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上下载,
下载地址:https://github.com/golang/crypto
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("文件下载成功")
}
以上为个人经验,希望能给大家一个参考,也希望大家多多支持asp之家。如有错误或未考虑完全的地方,望不吝赐教。
来源:https://blog.csdn.net/fu_qin/article/details/78741854
0
投稿
猜你喜欢
- 记录一次报错解决方法:No converter found capable of converting from type [java.la
- 本文实例讲述了JavaScript数据库TaffyDB用法。分享给大家供大家参考。具体如下:TaffyDB 是一个免费开源的 JavaScr
- 概述本文主要介绍一种降维方法,PCA(Principal Component Analysis,主成分分析)。降维致力于解决三类问题。1.
- 在sql语句后使用 SCOPE_IDENTITY() 当然您也可以使用 SELECT @@IDENTITY 但是使用 SELECT @@ID
- 没废话,直接上代码。环境说明:python3.6django2.0.5我们使用redis的作为celery任务队列,有一个合成包可以直接安装
- 前言:本文的主要内容是介绍Python中的列表及其方法的使用,涉及到的方法包括对列表元素进行修改、添加、删除、排序以及求列表长度等,此外还介
- 前言JavaScript语言中有一个非常重要又难以掌握,近似神话的概念-闭包。对于有一点JavaScript使用经验但从未真正理解闭包概念的
- 背景临时表空间用来管理数据库排序操作以及用于存储临时表、中间排序结果等临时对象,相信大家在开发中经常会遇到相关的需求,下面本文将给大家详细J
- vue2.0已经废弃了过滤器,需要自定义过滤器,用于一些常见的文本格式化。感觉超级好用!!过滤器可以用在两个地方:双花括号插值 和 v-bi
- python中函数定义参数有四种形式:def fun1(a,b,c): passdef fun2(a=1,b=2,c=3): &
- 删除 [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manage
- 看代码吧~import gcfor x in list(locals().keys())[:]: del loca
- 本文记录了笔者用 Python 爬取淘宝某商品的全过程,并对商品数据进行了挖掘与分析,最终得出结论。项目内容本案例选择>> 商品
- 相信有很多人有用程序向Excel导数据的需求, 且做过. 一般导出一些文本数据是很方便的, 可选方法很多, 比如拼接文本字符串存.cvs格式
- import time# time模块中包含了许多与时间相关的模块,其中通过time()函数可以获取当前的时间。count = 100pri
- 一 概念1. 原理2. 好处不同项目可能用到的环境不同,运用虚拟环境能将不同环境分隔开二 virtualenvvirtual 虚拟的1. 安
- mysql数据库没有增量备份的机制,当数据量太大的时候备份是一个很大的问题。还好mysql数据库提供了一种主从备份的机制,其实就是把主数据库
- 本文实例总结了Python3.5字符串常用操作。分享给大家供大家参考,具体如下:一、输入与输出#输入与输出str = input("
- 与大多数程序员一样,我经常需要标识存在于文本文档中的部件和结构,这些文档包括:日志文件、配置文件、分隔的数据以及格式更自由的(但还是半结构化
- 使用python实现文件导入,具体方法如下:文件样例可以自己random这里的temp1根据每一行的分隔符来读入,‘\n'表述回车t