feat: 新增fstp文件传输工具包
This commit is contained in:
@@ -6,12 +6,14 @@ import (
|
||||
"io"
|
||||
"os"
|
||||
"os/user"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"be.ems/src/framework/logger"
|
||||
"be.ems/src/framework/utils/cmd"
|
||||
gosftp "github.com/pkg/sftp"
|
||||
gossh "golang.org/x/crypto/ssh"
|
||||
)
|
||||
|
||||
@@ -239,12 +241,11 @@ func (s *SSHClientSession) Write(cmd string) (int, error) {
|
||||
return s.Stdin.Write([]byte(cmd))
|
||||
}
|
||||
|
||||
// Read 读取结果 等待一会才有结果
|
||||
// Read 读取结果
|
||||
func (s *SSHClientSession) Read() []byte {
|
||||
if s.Stdout == nil {
|
||||
return []byte{}
|
||||
}
|
||||
// time.Sleep(300 * time.Millisecond)
|
||||
bs := s.Stdout.Bytes()
|
||||
if len(bs) > 0 {
|
||||
s.Stdout.Reset()
|
||||
@@ -253,15 +254,6 @@ func (s *SSHClientSession) Read() []byte {
|
||||
return []byte{}
|
||||
}
|
||||
|
||||
// CombinedOutput 发送命令带结果返回
|
||||
func (s *SSHClientSession) CombinedOutput(cmd string) (string, error) {
|
||||
n, err := s.Write(cmd)
|
||||
if n == 0 || err != nil {
|
||||
return "", err
|
||||
}
|
||||
return string(s.Read()), nil
|
||||
}
|
||||
|
||||
// singleWriter SSH客户端会话消息
|
||||
type singleWriter struct {
|
||||
b bytes.Buffer
|
||||
@@ -283,3 +275,204 @@ func (w *singleWriter) Reset() {
|
||||
defer w.mu.Unlock()
|
||||
w.b.Reset()
|
||||
}
|
||||
|
||||
// NewClientSFTP 创建SSH客户端SFTP对象
|
||||
func (c *ConnSSH) NewClientSFTP() (*SSHClientSFTP, error) {
|
||||
sftpClient, err := gosftp.NewClient(c.Client)
|
||||
if err != nil {
|
||||
logger.Errorf("NewClientSFTP failed to create sftp: => %s", err.Error())
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &SSHClientSFTP{
|
||||
Client: sftpClient,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// SSHClientSFTP SSH客户端SFTP对象
|
||||
type SSHClientSFTP struct {
|
||||
Client *gosftp.Client
|
||||
}
|
||||
|
||||
// Close 关闭会话
|
||||
func (s *SSHClientSFTP) Close() {
|
||||
if s.Client != nil {
|
||||
s.Client.Close()
|
||||
}
|
||||
}
|
||||
|
||||
// CopyDirRemoteToLocal 复制目录-远程到本地
|
||||
func (s *SSHClientSFTP) CopyDirRemoteToLocal(remoteDir, localDir string) error {
|
||||
// 列出远程目录中的文件和子目录
|
||||
remoteFiles, err := s.Client.ReadDir(remoteDir)
|
||||
if err != nil {
|
||||
logger.Errorf("CopyDirRemoteToLocal failed to reading remote directory %s: => %s", remoteDir, err.Error())
|
||||
return err
|
||||
}
|
||||
|
||||
// 创建本地目录
|
||||
err = os.MkdirAll(localDir, 0755)
|
||||
if err != nil {
|
||||
logger.Errorf("CopyDirRemoteToLocal failed to creating local directory %s: => %s", localDir, err.Error())
|
||||
return err
|
||||
}
|
||||
|
||||
// 遍历远程文件和子目录并复制到本地
|
||||
for _, remoteFile := range remoteFiles {
|
||||
remotePath := filepath.Join(remoteDir, remoteFile.Name())
|
||||
localPath := filepath.Join(localDir, remoteFile.Name())
|
||||
|
||||
if remoteFile.IsDir() {
|
||||
// 如果是子目录,则递归复制子目录
|
||||
err = s.CopyDirRemoteToLocal(remotePath, localPath)
|
||||
if err != nil {
|
||||
logger.Errorf("CopyDirRemoteToLocal failed to copying remote directory %s: => %s", remotePath, err.Error())
|
||||
continue
|
||||
}
|
||||
} else {
|
||||
// 如果是文件,则复制文件内容
|
||||
remoteFile, err := s.Client.Open(remotePath)
|
||||
if err != nil {
|
||||
logger.Errorf("CopyDirRemoteToLocal failed to opening remote file %s: => %s", remotePath, err.Error())
|
||||
continue
|
||||
}
|
||||
defer remoteFile.Close()
|
||||
|
||||
localFile, err := os.Create(localPath)
|
||||
if err != nil {
|
||||
logger.Errorf("CopyDirRemoteToLocal failed to creating local file %s: => %s", localPath, err.Error())
|
||||
continue
|
||||
}
|
||||
defer localFile.Close()
|
||||
|
||||
_, err = io.Copy(localFile, remoteFile)
|
||||
if err != nil {
|
||||
logger.Errorf("CopyDirRemoteToLocal failed to copying file contents from %s to %s: => %s", remotePath, localPath, err.Error())
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// CopyDirRemoteToLocal 复制目录-本地到远程
|
||||
func (s *SSHClientSFTP) CopyDirLocalToRemote(localDir, remoteDir string) error {
|
||||
// 创建远程目录
|
||||
err := s.Client.MkdirAll(remoteDir)
|
||||
if err != nil {
|
||||
logger.Errorf("CopyDirLocalToRemote failed to creating remote directory %s: => %s", remoteDir, err.Error())
|
||||
return err
|
||||
}
|
||||
|
||||
// 遍历本地目录中的文件和子目录并复制到远程
|
||||
err = filepath.Walk(localDir, func(localPath string, info os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 生成远程路径
|
||||
remotePath := filepath.Join(remoteDir, localPath[len(localDir):])
|
||||
|
||||
if info.IsDir() {
|
||||
// 如果是子目录,则创建远程目录
|
||||
err := s.Client.MkdirAll(remotePath)
|
||||
if err != nil {
|
||||
logger.Errorf("CopyDirLocalToRemote failed to creating remote directory %s: => %s", remotePath, err.Error())
|
||||
return nil
|
||||
}
|
||||
} else {
|
||||
// 如果是文件,则复制文件内容
|
||||
localFile, err := os.Open(localPath)
|
||||
if err != nil {
|
||||
logger.Errorf("CopyDirLocalToRemote failed to opening local file %s: => %s", localPath, err.Error())
|
||||
return nil
|
||||
}
|
||||
defer localFile.Close()
|
||||
|
||||
remoteFile, err := s.Client.Create(remotePath)
|
||||
if err != nil {
|
||||
logger.Errorf("CopyDirLocalToRemote failed to creating remote file %s: => %s", remotePath, err.Error())
|
||||
return nil
|
||||
}
|
||||
defer remoteFile.Close()
|
||||
|
||||
_, err = io.Copy(remoteFile, localFile)
|
||||
if err != nil {
|
||||
logger.Errorf("CopyDirLocalToRemote failed to copying file contents from %s to %s: => %s", localPath, remotePath, err.Error())
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
logger.Errorf("CopyDirLocalToRemote failed to walking local directory: => %s", err.Error())
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// CopyDirRemoteToLocal 复制文件-远程到本地
|
||||
func (s *SSHClientSFTP) CopyFileRemoteToLocal(remotePath, localPath string) error {
|
||||
// 打开远程文件
|
||||
remoteFile, err := s.Client.Open(remotePath)
|
||||
if err != nil {
|
||||
logger.Errorf("CopyFileRemoteToLocal failed to opening remote file: => %s", err.Error())
|
||||
return err
|
||||
}
|
||||
defer remoteFile.Close()
|
||||
|
||||
// 如果目标文件已经存在,先将目标文件重命名
|
||||
if info, err := os.Stat(localPath); err == nil && !info.IsDir() {
|
||||
ext := filepath.Ext(localPath)
|
||||
name := localPath[0 : len(localPath)-len(ext)]
|
||||
newName := fmt.Sprintf("%s-%s%s", name, time.Now().Format("20060102_150405"), ext)
|
||||
err := os.Rename(localPath, newName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// 创建本地文件
|
||||
localFile, err := os.Create(localPath)
|
||||
if err != nil {
|
||||
logger.Errorf("CopyFileRemoteToLocal failed to creating local file: => %s", err.Error())
|
||||
return err
|
||||
}
|
||||
defer localFile.Close()
|
||||
|
||||
// 复制文件内容
|
||||
_, err = io.Copy(localFile, remoteFile)
|
||||
if err != nil {
|
||||
logger.Errorf("CopyFileRemoteToLocal failed to copying contents: => %s", err.Error())
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// CopyDirRemoteToLocal 复制文件-本地到远程
|
||||
func (s *SSHClientSFTP) CopyFileLocalToRemote(localPath, remotePath string) error {
|
||||
// 打开本地文件
|
||||
localFile, err := os.Open(localPath)
|
||||
if err != nil {
|
||||
logger.Errorf("CopyFileLocalToRemote failed to opening local file: => %s", err.Error())
|
||||
return err
|
||||
}
|
||||
defer localFile.Close()
|
||||
|
||||
// 创建远程文件
|
||||
remoteFile, err := s.Client.Create(remotePath)
|
||||
if err != nil {
|
||||
logger.Errorf("CopyFileLocalToRemote failed to creating remote file: => %s", err.Error())
|
||||
return err
|
||||
}
|
||||
defer remoteFile.Close()
|
||||
|
||||
// 复制文件内容
|
||||
_, err = io.Copy(remoteFile, localFile)
|
||||
if err != nil {
|
||||
logger.Errorf("CopyFileLocalToRemote failed to copying contents: => %s", err.Error())
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user