upload.go 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. package remote
  2. import (
  3. "bytes"
  4. "errors"
  5. "fmt"
  6. "io"
  7. "os"
  8. "path"
  9. "strings"
  10. "xg_auto_deploy/internal/global"
  11. "xg_auto_deploy/internal/models"
  12. "github.com/pkg/sftp"
  13. "golang.org/x/crypto/ssh"
  14. )
  15. // 字节的单位转换 保留两位小数
  16. func formatFileSize(s int64) (size string) {
  17. if s < 1024 {
  18. return fmt.Sprintf("%.2fB", float64(s)/float64(1))
  19. } else if s < (1024 * 1024) {
  20. return fmt.Sprintf("%.2fKB", float64(s)/float64(1024))
  21. } else if s < (1024 * 1024 * 1024) {
  22. return fmt.Sprintf("%.2fMB", float64(s)/float64(1024*1024))
  23. } else if s < (1024 * 1024 * 1024 * 1024) {
  24. return fmt.Sprintf("%.2fGB", float64(s)/float64(1024*1024*1024))
  25. } else if s < (1024 * 1024 * 1024 * 1024 * 1024) {
  26. return fmt.Sprintf("%.2fTB", float64(s)/float64(1024*1024*1024*1024))
  27. } else { //if s < (1024 * 1024 * 1024 * 1024 * 1024 * 1024)
  28. return fmt.Sprintf("%.2fEB", float64(s)/float64(1024*1024*1024*1024*1024))
  29. }
  30. }
  31. func UploadFile(nodeConfig *models.ServerNodeConfig, localFilePath string, targetFile string) error {
  32. // 1. 建立 ssh client
  33. client, err := ssh.Dial("tcp", nodeConfig.IpPort, nodeConfig.SSHClient)
  34. if err != nil {
  35. global.Logs.Fatal("ssh连接建立失败: ", err)
  36. return err
  37. }
  38. defer client.Close()
  39. // 2. 基于 ssh client 创建 sftp 客户端
  40. sftpClient, err := sftp.NewClient(client)
  41. if err != nil {
  42. // global.Log.Fatal("Failed to init sftp client: ", err)
  43. global.Logs.Fatal("sftp建立失败: ", err)
  44. return err
  45. }
  46. defer sftpClient.Close()
  47. // 3. 打开本地文件
  48. //取文件名字
  49. var remoteFileName string
  50. index := strings.LastIndex(localFilePath, "/")
  51. if index != -1 && index < len(localFilePath)-1 {
  52. remoteFileName = localFilePath[index+1:]
  53. } else {
  54. global.Logs.Fatal("获取文件名字失败无效")
  55. return fmt.Errorf("获取文件名字失败无效")
  56. }
  57. localFileName := localFilePath
  58. localFile, err := os.Open(localFileName)
  59. if err != nil {
  60. //global.Log.Fatal("Failed to open local file: ", err)
  61. global.Logs.Fatal("打开文件失败,", err)
  62. return err
  63. }
  64. defer localFile.Close()
  65. // 4. 创建远程服务器文件
  66. // 检测远端文件夹是否存在,不存在则创建 [ ! -d "/DATA2/GT/test" ] && mkdir -p /DATA2/GT/test
  67. SingleCmd(nodeConfig, fmt.Sprintf(`[ ! -d "%s" ] && mkdir -p %s`, targetFile, targetFile))
  68. //sftpClient.Mkdir(remotePath)
  69. target, err := sftpClient.Create(targetFile + "/" + remoteFileName)
  70. if err != nil {
  71. global.Logs.Fatal("创建远端文件失败 ", err)
  72. return err
  73. }
  74. defer target.Close()
  75. // 5. 数据复制
  76. n, err := io.Copy(target, localFile)
  77. if err != nil {
  78. global.Logs.Fatalf("节点 %s文件传输失败 %s ", nodeConfig.NodeId, err)
  79. return err
  80. }
  81. //获取本地文件大小
  82. localFileInfo, err := os.Stat(localFileName)
  83. if err != nil {
  84. global.Logs.Fatal("获取本地文件大小失败 ", err)
  85. return err
  86. }
  87. global.Logs.Printf("文件上传成功[文件%s 已上传到 %s/%s]本地文件大小:%s,上传文件大小:%s", localFileName, targetFile, remoteFileName, formatFileSize(localFileInfo.Size()), formatFileSize(n))
  88. return nil
  89. }
  90. // 上传文件buffer到目标端
  91. func UploadFileBuffer(nodeConfig *models.ServerNodeConfig, localBuffer *bytes.Buffer, targetFile string) error {
  92. // 1. 建立 ssh client
  93. client, err := ssh.Dial("tcp", nodeConfig.IpPort, nodeConfig.SSHClient)
  94. if err != nil {
  95. global.Logs.Fatal("Failed to dial: ", err)
  96. return errors.New("连接服务器失败 (Failed to dial)")
  97. }
  98. defer client.Close()
  99. // 2. 基于 ssh client 创建 sftp 客户端
  100. sftpClient, err := sftp.NewClient(client)
  101. if err != nil {
  102. global.Logs.Fatal("Failed to init sftp client: ", err)
  103. return errors.New(" 创建 sftp 客户端失败 (Failed to init sftp client)")
  104. }
  105. defer sftpClient.Close()
  106. // 4. 创建远程服务器文件
  107. target, err := sftpClient.Create(targetFile)
  108. if err != nil {
  109. global.Logs.Fatal("Failed to create remote file: ", err)
  110. return errors.New(" 创建远程服务器文件失败 (Failed to create remote file)")
  111. }
  112. defer target.Close()
  113. // 5. 数据复制File created successfully.
  114. _, err = io.Copy(target, localBuffer)
  115. if err != nil {
  116. global.Logs.Fatal("Failed to copy file: ", err)
  117. }
  118. return nil
  119. }
  120. // 递归上传文件夹内容
  121. func UploadDir(nodeConfig *models.ServerNodeConfig, localPath, remotePath string) error {
  122. global.Logs.Printf("-----节点%s 上传文件夹%s 到 目标端 %s ", nodeConfig.NodeId, localPath, remotePath)
  123. // 1. 建立 ssh client
  124. client, err := ssh.Dial("tcp", nodeConfig.IpPort, nodeConfig.SSHClient)
  125. if err != nil {
  126. global.Logs.Fatal("文件上传ssh连接建立失败: ", err)
  127. return err
  128. }
  129. defer client.Close()
  130. // 2. 基于 ssh client 创建 sftp 客户端
  131. sftpClient, err := sftp.NewClient(client)
  132. if err != nil {
  133. global.Logs.Fatal("sftp建立失败: ", err)
  134. return err
  135. }
  136. defer sftpClient.Close()
  137. var dirfunc func(nodeConfig *models.ServerNodeConfig, localPath, remotePath string, localFiles []os.DirEntry) error
  138. dirfunc = func(nodeConfig *models.ServerNodeConfig, localPath, remotePath string, localFiles []os.DirEntry) error {
  139. for _, file := range localFiles {
  140. localFilePath := path.Join(localPath, file.Name())
  141. remoteFilePath := path.Join(remotePath, file.Name())
  142. //fmt.Printf("localFilePath: %s, remoteFilePath: %s\n", localFilePath, remoteFilePath)
  143. if file.IsDir() {
  144. subLocalFiles, err := os.ReadDir(localFilePath)
  145. if err != nil {
  146. global.Logs.Fatalf("读取文件夹失败: %s, err:%s", localFilePath, err)
  147. return err
  148. }
  149. //_, err = SingleCmd(nodeConfig, fmt.Sprintf(`[ ! -d "%s" ] `, remoteFilePath))
  150. err = sftpClient.Mkdir(remoteFilePath)
  151. if err != nil {
  152. global.Logs.Fatalf("创建文件夹失败 ( 查看目标端目录文件夹是否已存在 ): %s, err:%s", remoteFilePath, err)
  153. return err
  154. }
  155. err = dirfunc(nodeConfig, localFilePath, remoteFilePath, subLocalFiles)
  156. if err != nil {
  157. global.Logs.Fatalf("递归上传文件夹失败: %s, err:%s", localFilePath, err)
  158. return err
  159. }
  160. } else {
  161. srcFile, err := os.Open(localFilePath)
  162. if err != nil {
  163. global.Logs.Fatalf("打开文件失败: %s, err:%s", localFilePath, err)
  164. return err
  165. }
  166. defer srcFile.Close()
  167. dstFile, err := sftpClient.Create(remoteFilePath)
  168. if err != nil {
  169. global.Logs.Fatalf("创建文件失败: %s, err:%s", remoteFilePath, err)
  170. return err
  171. }
  172. defer dstFile.Close()
  173. _, err = io.Copy(dstFile, srcFile)
  174. if err != nil {
  175. global.Logs.Fatalf("节点 %s 文件传输失败: %s, err:%s ", nodeConfig.NodeId, remoteFilePath, err)
  176. return err
  177. }
  178. }
  179. }
  180. return nil
  181. }
  182. localFiles, err := os.ReadDir(localPath)
  183. if err != nil {
  184. return err
  185. }
  186. err = dirfunc(nodeConfig, localPath, remotePath, localFiles)
  187. if err != nil {
  188. return err
  189. }
  190. return nil
  191. }