最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Go語言實現(xiàn)ssh&scp的方法詳解

 更新時間:2022年10月09日 14:44:06   作者:漫漫Coding路  
這篇文章主要為大家詳細介紹了如何利用Go語言實現(xiàn)ssh&scp,文中的示例代碼講解詳細,具有一定的參考價值,感興趣的小伙伴可以了解一下

前言

最近遇到一個臨時需求,需要將客戶環(huán)境中一個服務(wù)每天的日志進行一系列復(fù)雜處理,并生成數(shù)據(jù)報表。由于數(shù)據(jù)處理邏輯復(fù)雜,且需要存入數(shù)據(jù)庫,在客戶環(huán)境使用 shell 腳本無法處理,因此就需要將日志先拷貝到本地,再進行處理;同時為了避免每天人工拷貝日志,需要實現(xiàn)自動化,整條鏈路自動執(zhí)行,無需人工干預(yù)。平時使用 Go 語言較多,由此就引出了 Go 語言 ssh 連接遠程客戶服務(wù)器,并利用 scp 將數(shù)據(jù)拷貝下來的一系列操作。

說明:本文中的示例,均是基于Go1.17 64位機器

連接遠程服務(wù)器并執(zhí)行命令(ssh)

如下給出了使用 用戶名+密碼 的方式連接遠程服務(wù)器并執(zhí)行了 /usr/bin/whoami 命令的示例,步驟如下:

  • 生成 ClientConfig:想要連接遠程服務(wù)器,必須要至少指定一種實現(xiàn)了 Auth 的 AuthMethod,我們這里使用密碼的方式;同時需要提供 一種用于安全校驗遠程服務(wù)端key的方法 HostKeyCallback,我們這里使用的是不校驗的方式 ssh.InsecureIgnoreHostKey(),生產(chǎn)情況下建議使用 ssh.FixedHostKey(key PublicKey);
  • 調(diào)用 Dial :Dial 方法與遠程服務(wù)器建立連接,并返回一個 client ;
  • NewSessionNewSession方法開啟一個會話,在一個會話內(nèi)可以通過 Run 方法執(zhí)行一個命令。
import?(
?"bytes"
?"fmt"
?"log"
??
??"golang.org/x/crypto/ssh"
)

func?main()?{

?var?(
??username?=?"your?username"
??password?=?"your?password"
??addr?????=?"ip:22"
?)
?
?config?:=?&ssh.ClientConfig{
??User:?username,
??Auth:?[]ssh.AuthMethod{
???ssh.Password(password),
??},
??HostKeyCallback:?ssh.InsecureIgnoreHostKey(),
?}
?client,?err?:=?ssh.Dial("tcp",?addr,?config)
?if?err?!=?nil?{
??log.Fatal("Failed?to?dial:?",?err)
?}
?defer?client.Close()

?//?開啟一個session,用于執(zhí)行一個命令
?session,?err?:=?client.NewSession()
?if?err?!=?nil?{
??log.Fatal("Failed?to?create?session:?",?err)
?}
?defer?session.Close()

?//?執(zhí)行命令,并將執(zhí)行的結(jié)果寫到?b?中
?var?b?bytes.Buffer
?session.Stdout?=?&b
??
??//?也可以使用?session.CombinedOutput()?整合輸出
?if?err?:=?session.Run("/usr/bin/whoami");?err?!=?nil?{
??log.Fatal("Failed?to?run:?"?+?err.Error())
?}
?fmt.Println(b.String())??//?root
}

上面的例子,我們在 Run 方法里面?zhèn)魅肓艘粋€命令,然后遠程服務(wù)器會將執(zhí)行結(jié)果返回給我們,如果是復(fù)雜操作,通過傳入命令的方式就比較麻煩。比如上面提到的需求,需要我從 k8s 容器中拷貝出服務(wù)每天的日志,拆解后的步驟為:獲取服務(wù)的多個 k8s pod 名稱,根據(jù)當前日期,從多個容器中分別拷貝日志文件,然后整合成一個日志文件。針對復(fù)雜操作,我們可以在遠程服務(wù)器編寫一個腳本,然后 Run 方法中傳入執(zhí)行腳本的命令。

簡單舉個示例,我們在遠程服務(wù)器編寫了一個腳本 test.sh,放在了 /opt 目錄下,腳本內(nèi)容 與 調(diào)用方式分別如下:

#?腳本文件
#!/bin/bash
today=$(date?+"%Y-%m-%d")
#?將數(shù)據(jù)寫入文件
$(df?-h?>?$today.log)
package?main

import?(
?"fmt"
?"log"
??
??"golang.org/x/crypto/ssh"
)

func?main()?{

?var?(
??username?=?"your?username"
??password?=?"your?password"
??addr?????=?"ip:22"
?)

?config?:=?&ssh.ClientConfig{
??User:?username,
??Auth:?[]ssh.AuthMethod{
???ssh.Password(password),
??},
??HostKeyCallback:?ssh.InsecureIgnoreHostKey(),
?}
?client,?err?:=?ssh.Dial("tcp",?addr,?config)
?if?err?!=?nil?{
??log.Fatal("Failed?to?dial:?",?err)
?}
?defer?client.Close()


?session,?err?:=?client.NewSession()
?if?err?!=?nil?{
??log.Fatal("Failed?to?create?session:?",?err)
?}
?defer?session.Close()

??//?調(diào)用遠程服務(wù)器腳本腳本
?res,?err?:=?session.CombinedOutput("sh?/opt/test.sh")
?if?err?!=?nil?{
??log.Fatal("Failed?to?run:?"?+?err.Error())
?}
?fmt.Println(string(res))
??
??/*
??Filesystem??????Size??Used?Avail?Use%?Mounted?on
??devtmpfs????????909M?????0??909M???0%?/dev
??tmpfs???????????919M???24K??919M???1%?/dev/shm
??tmpfs???????????919M??540K??919M???1%?/run
??tmpfs???????????919M?????0??919M???0%?/sys/fs/cgroup
??/dev/vda1????????50G??6.9G???40G??15%?/
??tmpfs???????????184M?????0??184M???0%?/run/user/0
??*/
}

拷貝遠程服務(wù)器文件到本地(scp)

拷貝文件步驟比較簡單:

  • 建立 ssh client
  • 基于 ssh client 創(chuàng)建 sftp client
  • 打開遠程服務(wù)器文件并拷貝到本地
package?main

import?(
?"io"
?"log"
?"os"
?"time"
??
??"github.com/pkg/sftp"
?"golang.org/x/crypto/ssh"
)

func?main()?{

?var?(
??username?=?"your?username"
??password?=?"your?password"
??addr?????=?"ip:22"
?)

?//?1.?建立?ssh?client
?config?:=?&ssh.ClientConfig{
??User:?username,
??Auth:?[]ssh.AuthMethod{
???ssh.Password(password),
??},
??HostKeyCallback:?ssh.InsecureIgnoreHostKey(),
?}
?client,?err?:=?ssh.Dial("tcp",?addr,?config)
?if?err?!=?nil?{
??log.Fatal("Failed?to?dial:?",?err)
?}
?defer?client.Close()

?//?2.?基于ssh?client,?創(chuàng)建?sftp?客戶端
?sftpClient,?err?:=?sftp.NewClient(client)
?if?err?!=?nil?{
??log.Fatal("Failed?to?init?sftp?client:?",?err)
?}
?defer?sftpClient.Close()

?//?3.?打開遠程服務(wù)器文件
?filename?:=?time.Now().Format("2006-01-02")?+?".log"
?source,?err?:=?sftpClient.Open("/opt/"?+?filename)
?if?err?!=?nil?{
??log.Fatal("Failed?to?open?remote?file:?",?err)
?}
?defer?source.Close()

?//?4.?創(chuàng)建本地文件
?target,?err?:=?os.OpenFile(filename,?os.O_RDWR|os.O_CREATE|os.O_TRUNC,?0644)
?if?err?!=?nil?{
??log.Fatal("Failed?to?open?local?file:?",?err)
?}
?defer?target.Close()

?//?5.?數(shù)據(jù)復(fù)制
?n,?err?:=?io.Copy(target,?source)
?if?err?!=?nil?{
??log.Fatal("Failed?to?copy?file:?",?err)
?}
?log.Println("Succeed?to?copy?file:?",?n)

}

在 sftp client 中,還有許多方法,例如 WalkReadDirStat、Mkdir等,針對文件也有 Read、Write、WriteToReadFrom等方法,像操作本地文件系統(tǒng)一樣,非常便利。

簡單封裝下

package?main

import?(
?"fmt"
?"io"
?"log"
?"os"
?"time"

?"github.com/pkg/sftp"
?"golang.org/x/crypto/ssh"
)

type?Cli?struct?{
?user???string
?pwd????string
?addr???string
?client?*ssh.Client
}


func?NewCli(user,?pwd,?addr?string)?Cli?{
?return?Cli{
??user:?user,
??pwd:??pwd,
??addr:?addr,
?}
}

//?Connect?連接遠程服務(wù)器
func?(c?*Cli)?Connect()?error?{
?config?:=?&ssh.ClientConfig{
??User:?c.user,
??Auth:?[]ssh.AuthMethod{
???ssh.Password(c.pwd),
??},
??HostKeyCallback:?ssh.InsecureIgnoreHostKey(),
?}
?client,?err?:=?ssh.Dial("tcp",?c.addr,?config)
?if?nil?!=?err?{
??return?fmt.Errorf("connect?server?error:?%w",?err)
?}
?c.client?=?client
?return?nil
}

//?Run?運行命令
func?(c?Cli)?Run(shell?string)?(string,?error)?{
?if?c.client?==?nil?{
??if?err?:=?c.Connect();?err?!=?nil?{
???return?"",?err
??}
?}

?session,?err?:=?c.client.NewSession()
?if?err?!=?nil?{
??return?"",?fmt.Errorf("create?new?session?error:?%w",?err)
?}
?defer?session.Close()

?buf,?err?:=?session.CombinedOutput(shell)
?return?string(buf),?err
}

//?Scp?復(fù)制文件
func?(c?Cli)?Scp(srcFileName,?targetFileName?string)?(int64,?error)?{
?if?c.client?==?nil?{
??if?err?:=?c.Connect();?err?!=?nil?{
???return?0,?err
??}
?}

?sftpClient,?err?:=?sftp.NewClient(c.client)
?if?err?!=?nil?{
??return?0,?fmt.Errorf("new?sftp?client?error:?%w",?err)
?}
?defer?sftpClient.Close()

?source,?err?:=?sftpClient.Open(srcFileName)
?if?err?!=?nil?{
??return?0,?fmt.Errorf("sftp?client?open?file?error:?%w",?err)
?}
?defer?source.Close()

?target,?err?:=?os.OpenFile(targetFileName,?os.O_RDWR|os.O_CREATE|os.O_TRUNC,?0644)
?if?err?!=?nil?{
??return?0,?fmt.Errorf("open?local?file?error:?%w",?err)
?}
?defer?target.Close()

?n,?err?:=?io.Copy(target,?source)
?if?err?!=?nil?{
??return?0,?fmt.Errorf("copy?file?error:?%w",?err)
?}
?return?n,?nil
}


//?調(diào)用測試
func?main()?{
?var?(
??username?=?"your?username"
??password?=?"your?password"
??addr?????=?"ip:22"
?)

?//?初始化
?client?:=?NewCli(username,?password,?addr)

?//?ssh?并運行腳本
?_,?err?:=?client.Run("sh?/opt/test.sh")
?if?err?!=?nil?{
??log.Printf("failed?to?run?shell,err=[%v]\n",?err)
??return
?}

?//?scp?文件到本地
?filename?:=?time.Now().Format("2006-01-02")?+?".log"
?n,?err?:=?client.Scp("/opt/"+filename,?filename)
?if?err?!=?nil?{
??log.Printf("failed?to?scp?file,err=[%v]\n",?err)
??return
?}
?log.Printf("Succeed?to?scp?file,?size=[%d]\n",?n)

?//?處理文件并刪除本地文件......
}

通過上面的一系列操作,就可以實現(xiàn)了我的需求:

1.編寫程序:

  • 連接客戶服務(wù)器
  • 執(zhí)行遠程服務(wù)器的腳本,生成日志文件
  • 拷貝遠程服務(wù)器的日志文件到本地
  • 處理日志文件
  • 刪除本地文件

2.在服務(wù)器上啟動一個定時任務(wù)運行該程序

以上就是Go語言實現(xiàn)ssh&scp的方法詳解的詳細內(nèi)容,更多關(guān)于Go語言實現(xiàn)ssh scp的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 在Go語言開發(fā)中實現(xiàn)高性能的分布式日志收集的方法

    在Go語言開發(fā)中實現(xiàn)高性能的分布式日志收集的方法

    本文介紹了在Go語言開發(fā)中實現(xiàn)高性能分布式日志收集的關(guān)鍵步驟和考慮因素,包括日志生成與采集、日志傳輸、日志收集器的高性能網(wǎng)絡(luò)I/O、日志存儲與分析、監(jiān)控與告警系統(tǒng)、擴展性與可維護性等方面,本文給大家介紹的非常詳細,感興趣的朋友一起看看吧
    2025-01-01
  • Go語言程序開發(fā)gRPC服務(wù)

    Go語言程序開發(fā)gRPC服務(wù)

    這篇文章主要為大家介紹了Go語言程序開發(fā)gRPC服務(wù),有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-06-06
  • GO中Json解析的幾種方式

    GO中Json解析的幾種方式

    本文主要介紹了GO中Json解析的幾種方式,詳細的介紹了幾種方法,?文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2024-01-01
  • 一文詳解Golang連接kafka的基本操作

    一文詳解Golang連接kafka的基本操作

    這篇文章主要為大家詳細介紹了Golang中連接kafka的基本操作的相關(guān)知識,文中的示例代碼講解詳細,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2025-03-03
  • 聊聊Golang性能分析工具pprof的使用

    聊聊Golang性能分析工具pprof的使用

    對于線上穩(wěn)定運行的服務(wù)來說,?可能會遇到?cpu、mem?利用率升高的問題,那我們就需要使用?pprof?工具來進行性能分析,所以本文就來和大家講講pprof的具體使用吧
    2023-05-05
  • golang抓取tcp包的實現(xiàn)方式

    golang抓取tcp包的實現(xiàn)方式

    使用`golang`的`packet`和`pcap`庫可以抓取TCP數(shù)據(jù)包,首先,確保安裝了`pcap`庫,然后使用以下代碼打開網(wǎng)絡(luò)接口,設(shè)置過濾規(guī)則為“tcp”,開始捕獲并解析TCP數(shù)據(jù)包,運行代碼時需要管理員權(quán)限
    2024-12-12
  • 詳解Go語言中init的使用與常見應(yīng)用場景

    詳解Go語言中init的使用與常見應(yīng)用場景

    Go?中有一個特別的?init()?函數(shù),它主要用于包的初始化,這篇文章將以此為主題介紹?Go?中?init()?函數(shù)的使用和常見使用場景,希望對大家有所幫助
    2024-02-02
  • Golang爬蟲及正則表達式的實現(xiàn)示例

    Golang爬蟲及正則表達式的實現(xiàn)示例

    本文主要介紹了Golang爬蟲及正則表達式的實現(xiàn)示例,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-12-12
  • golang?gorm框架數(shù)據(jù)庫的連接操作示例

    golang?gorm框架數(shù)據(jù)庫的連接操作示例

    這篇文章主要為大家介紹了golang?gorm框架數(shù)據(jù)庫操作示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步早日升職加薪
    2022-04-04
  • GO 切片刪除元素的三種方法

    GO 切片刪除元素的三種方法

    本文主要介紹了GO 切片刪除元素,根據(jù)要刪除元素的位置有三種情況,分別是從開頭位置刪除、從中間位置刪除和從尾部刪除,具有一定的參考價值,感興趣的可以了解一下
    2024-08-08

最新評論

梧州市| 长寿区| 云浮市| 新泰市| 兰州市| 格尔木市| 藁城市| 灵宝市| 合山市| 桐梓县| 措美县| 汶川县| 瑞昌市| 浙江省| 格尔木市| 健康| 随州市| 兰考县| 陈巴尔虎旗| 平遥县| 南康市| 通山县| 平南县| 齐齐哈尔市| 湾仔区| 神木县| 灵武市| 台中市| 湘潭县| 富宁县| 牡丹江市| 阳江市| 石林| 崇信县| 左云县| 博爱县| 毕节市| 咸丰县| 冀州市| 河南省| 南乐县|