1. 程式人生 > >GO實現簡單(命令列)工具:sftp,文件壓解,RDS備份,RDS備份下載

GO實現簡單(命令列)工具:sftp,文件壓解,RDS備份,RDS備份下載

GO實現簡單(命令列)工具:sftp,文件壓解,RDS備份,RDS備份下載

轉載請註明出處:https://www.cnblogs.com/funnyzpc/p/11721978.html

內容提要:

  • 1.遠端連線linux執行sftp檔案下載
  • 2.window下檔案解壓縮(tar、gz、zip)
  • 3.window下檔案解壓縮及帶密碼解壓(zip)
  • 4.window下呼叫阿里雲RDS api查詢備份並下載
  • 5.GO語言命令列工具技巧
      首先,寫這篇博文的一個出發點是:我無法在window的cmd命令列下實現日期的加減(還有其他問題),當然這不是沒有實現的方法,而是實現起來很難維護難度較大,光外掛都夠我折騰了,另外window自帶的powershell也可以實現,不過作為一個java渣來說真的難了點兒,因為又要熟悉powershell語法從零開始
      後來,我換了個思路,想用程式碼+第三方開源外掛(依賴)實現以上功能;至於,目前我有對Python、java、js、Go、甚至Rust,這些都有或多或少的涉獵,分析了一遍,發現使用半靜態或者指令碼語言實現很easy,不過有一個問題:你每部署一臺機器都要安裝語言環境如Python、java,雖然可以跨平臺,不過太臃腫了部署一個幾兆的應用要安裝一個幾百兆的語言環境,實在太浪費了記憶體,js呢又太弱,需要自己造輪子,可以剔除,Rust速度快,不過編寫的難度太大,很難考慮,
      最後我選用GO作為以上工具的語言,當然這裡不得不說一下使用GO的好處:語法簡單、跨平臺、程式碼安全、靜態打包:這個很重要,可以直接打windows下的可執行程式,也可以打linux可執行程式[交叉編譯],這樣就可以在部署的時候不用動手又動腳的安裝語言環境,配置環境變數之類的亂七八糟的東西,同時安全度也很複合我的需求,例如打成一個可執行包後就自帶破解難度,更牛掰的是還可以使用upx對可執行包進行加殼,加殼有三個好處:幾乎無法破解、可執行應用體積大大縮小(比我的一個應用打包後有16MB,加殼後只有3MB左右)、易於分發(當然這個是建立在加殼之上在),一切準備就緒,這一篇我就簡單的聊一聊我用GO如何實現這類Tools。

由於本章只是個人實現的工具分享,因為這些工具有一定的靈活性,(若需要改造或實現)這時就需要您有一定的GO語言基礎。

1.遠端連線 example: log_bak01.go

這裡的我主要用到 github.com/pkg/sftpgolang.org/x/crypto/ssh,一個是執行sftp命令,一個是建立ssh連線的,因為sftp是建立在安全的ssh連線上的
樣例中有我實現實現linux日誌拉取的功能的完整程式碼,,這裡就不展示具體實現程式碼(參考樣例),就簡單說說實現步驟吧:

  • 建立ssh配置
    • config := &ssh.ClientConfig{...
  • 建立建立ssh的TCP連線(ssh是建立在TCP連線上的)
    • client, err := ssh.Dial("tcp", "伺服器地址:埠", config)
  • 使用ssh連線建立一個sftp連線J(sftp在使用完畢後必須close())
    • sftp, err := sftp.NewClient(client)
  • 開啟一個Linux系統檔案(在本地檔案寫入後遠端檔案必須close())
    • srcFile, err := sftp.Open("/路徑/檔案01.log." + time + ".zip")
  • 建立一個本地下載檔案(本地檔案寫入完成後需要close())
    • dstFile, err := os.Create(targetPath + "/檔案01.log." + time + ".zip")
  • 將連結的遠端檔案寫入到本地下載檔案
    • srcFile.WriteTo(dstFile)
  • 以上步驟的具體程式碼可以參考: log_bak01.go

2.window下檔案解壓縮(tar、gz、zip) example: gzip_util.go,unzip_util.go

由於在解決實際問題的時候面臨的問題比較複雜,光一個壓縮包就有zip、tar、gz還有tar+gz的方式,具體使用的時候用到的依賴有
archive/tarcompress/gziparchive/zippath/filepath及GO自帶的基本依賴等等...

  • 對於zip就比較簡單
    • 首先你得傳入一個zip檔案全路徑,然後使用zip的讀模式open這個zip檔案
      • r, err := zip.OpenReader(fullZipFile)
    • 遍歷這個讀取的zip檔案,並迴圈(迴圈完畢需要將這個zip檔案close())
      • for _, f := range r.File {...
    • 每迴圈到一個目錄的時候在local建立這個資料夾
      • os.MkdirAll(path, f.Mode())
    • 每迴圈到一個檔案的時候先在local建立目錄並以寫模式open這個檔案,然後將迴圈到的檔案寫入到這個local檔案(寫入完成需要close())
      • os.MkdirAll(filepath.Dir(path), f.Mode())
      • f, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, f.Mode())
      • _, err = io.Copy(f, rc)
  • 對於tar+gz檔案的處理方法
    • 首先您需要以讀模式Open這個檔案(在這個壓縮文件全部解壓後需要close())
      • fr, err := os.Open(srcFilePath)
    • 因為大多數這種組合的壓縮文件都是先tar然後再gz,所以這裡我們就先使用gzip依賴讀取這個文件
      • gr, err := gzip.NewReader(fr)
    • 讀取gzip成功後,這時候需要使用tar依賴讀取這個tar文件
      • tr := tar.NewReader(gr)
    • 遍歷迴圈這個讀取到的tar文件並寫入目錄及檔案(注意local文件在寫入完成之後需要close())
      • for {...

3.window下zip檔案帶密碼解壓 example: unpzip_util.go

其實官方給的example中並沒有帶祕密的解壓縮,這個問題困擾了我幾個小時,最終在我碰到有網友寫的這個依賴才得以解決:github.com/yeka/zip",再次表示十分
感謝,在此能將example共享出來也算是功德一件哈~

這裡的處理其實十分簡單,其實就是在每次迴圈zip檔案的時候判斷一下IsEncrypted(),在true的時候SetPassword(password) ,後面使用io之後的檔案就是
非加密檔案了,so easy ~

  • 需要使用依賴的Open這個zip檔案
    • r, err := zip.OpenReader(fullZipFile)
  • 遍歷迴圈這個zip檔案
    • for _, f := range r.File {...
  • 在每迴圈到一個檔案及目錄的時候設定一下password
    • f.SetPassword(password)
  • 將當前讀取到的檔案及目錄寫入到local
    • func writeFile(filePath string, f *zip.File) error {...

4.window下呼叫阿里雲RDS api查詢備份並下載 example: main1.go

其實這是對前幾個功能對一個綜合,我對目的是下載阿里雲的RDS的物理備份並解壓,當然你需要先參閱官方api文件,在這裡DescribeBackups
其實一開始我並不知道,所有的備份檔案都需要查詢到其下載連結後才可下載,獲取到下載連結後其他的事情就按部就班了~,以下是我實現的思路,可參閱~

  • 參閱官方文件並使用api查詢備份檔案(官方有api的除錯程式碼)
    • client, err := rds.NewClientWithAccessKey("cn-hangzhou", "您的accessKeyId", "您的accessKeySecret")
    • request := rds.CreateDescribeBackupsRequest()
    • respJsonStr, err := client.DescribeBackups(request)
  • 因為查詢到的資料為json的字串形式,這時候需要將json轉換成struct
    • data := &BackupInfo{}
    • json.Unmarshal(respJsonStr.GetHttpContentBytes(), data)
  • 迴圈或直接呼叫這個結構體例項獲取到下載地址及相關引數
    • downloadUrl := data.Items.BackupItem[0].BackupDownloadURL
    • backupDate := data.Items.BackupItem[0].BackupStartTime[0:10]
  • 下載檔案
    • err := util.DownloadFile(downloadUrl, filePath)
  • 解壓檔案
    • err2 := util.UnTarGz(filePath, unTarGzFilePath)

5.GO語言命令列工具技巧 example main3.go

一開始我是想將打包好的tools部署後使用命令列呼叫,這樣會顯得靈活一些,後來覺得這樣使用太過與零碎了,而且window下的執行環境也是個問題,最後才做決定將一組
功能當堵打包,然後使用windows的計畫任務呼叫,不過既然作為一種可行的方式(linux下比較可行),所以就參閱了個簡單的Demo,讀者可以根據這個Demo改寫上述功能

這裡是結合著命令列實現了個檔案下載功能

  • GO語言開發環境自帶os包,使用os.Args獲取呼叫的所有呼叫的引數,這個args\[0\]是你打包好的exe可執行程式本身(windows環境下)
    • 比如你的命令列是 main_exec.exe https://www.xxx.com/path/xx.zip D:/tmp
    • 使用os.Args獲取到的引數有仨 os.Args[0]:main_exec.exe,os.Args[1]:https://www.xxx.com/path/xx.zip,os.Args[2]:D:/tmp
  • 從命令列引數中獲取下載地址和目錄引數
    • url := os.Args[1] filename := os.Args[2]
  • 呼叫download工具下載這個網路檔案
    • err := util.DownloadFile(url, filename)

最後

本章的內容比較零散,望讀者諒解,另外,以上內容的所有程式碼(包括已經打包好的exe程式)我已推送至github rds_backup
這些程式碼全部使用GO語言實現,當然以上內容可能並不完整,全黨是拋磚引玉,一個解決問題的方式,如有需要改進或優化的地方請留言哈