golang怎么實現ssh

這篇文章主要介紹“golang怎么實現ssh”,在日常操作中,相信很多人在golang怎么實現ssh問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”golang怎么實現ssh”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!

成都創新互聯公司堅持“要么做到,要么別承諾”的工作理念,服務領域包括:網站制作、做網站、企業官網、英文網站、手機端網站、網站推廣等服務,滿足客戶于互聯網時代的泰寧網站設計、移動媒體設計的需求,幫助企業找到有效的互聯網解決方案。努力成為您成熟可靠的網絡建設合作伙伴!

1.ssh

1.1 前言

在日常的一些開發場景中,我們需要去和遠程服務器進行一些通信,執行一些相關命令操作,這個時候我們就可以使用SSH協議實現目標。SSH協議是建立在應用層上的安全協議,全稱為Secure Shell,采用的是面向連接的TCP協議進行傳輸,也就意味著它是安全可靠的。需要注意的是文件傳輸并不能在SSH協議上完成,需要在下面提到的SFTP協議完成。

1.2 Go實現

Go官方為我們提供了用于實現SSH連接的package,位于golang.org/x/crypto下,通過在程序中調用包中提供的相關方法,便可以實現與其他機器進行通信。使用前我們需要使用go get導入相關的依賴包。

go get golang.org/x/crypto/ssh

1.2.1 配置相關參數

在進行通信之前,我們還需要配置一些用于配置一些用于建立連接的相關參數。ssh包下的ClientConfig結構體中,定義了建立SSH連接需要用到的一些配置項,部分項提供了默認參數,我們使用時可以不進行聲明。

下面的代碼段中,我們首先是聲明了用戶名和密碼,連接超時時間設置為10秒鐘,addr變量定義了目標機器的IP地址以及端口。

HostKeyCallback項,我們設置了忽略,這是因為SSH協議為客戶端提供了兩種安全驗證方式,一種是基于口令的安全驗證,也就是我們常常使用的賬號密碼形式,另外一種則是基于密鑰的安全驗證,相較于第一種,這種形式的校驗方法極大的提升了安全等級,缺點則是時間損耗相對較長。

如果需要使用這種方式進行校驗,首先我們需要在服務器上為自己創建一對密鑰,作為客戶端進行訪問時,首先會向服務端發送安全驗證請求,服務端收到請求后,首先會將機器上保存的公鑰與客戶端發送的公鑰進行比較,如果一致,服務端則會向客戶端響應加密質詢,客戶端接受到質詢之后,使用私鑰進行解密,然后再將解密結果發送給服務端,服務端進行校驗后再返回響應結果,到這里就算是完成了一段密鑰校驗。

        //添加配置
        config := &ssh.ClientConfig{
                User: "root",
                Auth: []ssh.AuthMethod{ssh.Password("Password")},
                HostKeyCallback: ssh.InsecureIgnoreHostKey(),
                Timeout: 10 * time.Second,
            }
        }
        addr := fmt.Sprintf("%v:%v", IP, Port)

1.2.2 建立連接

在完成了所有的參數初始化之后,我們便可以調用Dial方法建立SSH連接。Dial方法一共有三個參數和兩個返回值,第一個參數network為網絡類型,這里我們使用面向連接的TCP協議,第二個參數addr則為目標機器的IP地址和端口號,第三個參數config則為前面我們生命的配置項。Dial會返回一個SSH連接和錯誤類型。

func Dial(network, addr string, config *ClientConfig) (*Client, error)

        //建立SSH連接
        sshClient, err := ssh.Dial("tcp", addr, config)       
         if err != nil {
            log.Fatal("unable to create ssh conn")
        }

1.2.3 創建會話

在建立了與目標機器的SSH連接之后,我們就可以通過創建SSH會話來與目標機器進行通信。通過NewSession()方法便可以實現這一操作。

        //建立SSH會話
        sshSession, err := sshClient.NewSession()       if err != nil {
           log.Fatal("unable to create ssh session")
        }

1.2.4 執行操作

與目標機器建立會話后,我們就可以通過執行命令等來操作遠程服務器。Go目前為我們提供了五個用于操作遠程機器的方法,分別是Run(), Start(), Output(), CombineOutpt(), Shell()

?其中 Output(), **CombineOutpt()**這兩個方法是對Run()方法進行不同程度上的封裝,校驗了輸出流,錯誤流等相關內容。

        // Output runs cmd on the remote host and returns its standard output.
        func (s *Session) Output(cmd string) ([]byte, error) {           if s.Stdout != nil {              return nil, errors.New("ssh: Stdout already set")
           }           var b bytes.Buffer
           s.Stdout = &b
           err := s.Run(cmd)           return b.Bytes(), err
        }        
        
        // CombinedOutput runs cmd on the remote host and returns its combined
        // standard output and standard error.
        func (s *Session) CombinedOutput(cmd string) ([]byte, error) {           if s.Stdout != nil {              return nil, errors.New("ssh: Stdout already set")
           }           if s.Stderr != nil {              return nil, errors.New("ssh: Stderr already set")
           }           var b singleWriter
           s.Stdout = &b
           s.Stderr = &b
           err := s.Run(cmd)           return b.b.Bytes(), err
        }

Run()方法則是對Start()方法進行了封裝,添加了Wait方法,用于校驗遠程服務器的退出指令。Wait()方法中有一個管道類型的變量exitStatus,它是用來保存每次執行命令后,機器返回的退出狀態的。有興趣的朋友可以去看看這塊的代碼,這里就不貼代碼了。

這里面有一個坑,如果我們在遠程機器上去運行一個永遠不會停止的程序,這個時候我們的程序一直等待不到遠程機器發送的退出指令,就會造成程序一直阻塞而無法正常返回。解決的辦法是用一個協程去單獨執行這一塊的任務,或者是使用定時器來定時結束session會話,來正常返回。

Start()方法與Shell方法一致,都是返回一個error類型,在底層都是調用了start()方法和SendRequest方法,關于這兩個方法的內容這里就不做詳細介紹了,有興趣的朋友可以自行去閱讀。唯一的區別是Start()方法有一個string類型的參數,用于接收用戶輸入的參數,而Shell()方法是無參數的。

使用Shell()方法配合RequestPty()等方法可以在本地建立一個偽終端,可以直接通過輸入命令的形式操作目標機器。下面都會做一個示例。

        //Run
        func (s *Session) Run(cmd string) error {
           err := s.Start(cmd)           if err != nil {
              fmt.Println(err)              return err
           }           return s.Wait()
                }                
                
        // Start runs cmd on the remote host. Typically, the remote
        // server passes cmd to the shell for interpretation.
        // A Session only accepts one call to Run, Start or Shell.
        func (s *Session) Start(cmd string) error {           if s.started {              return errors.New("ssh: session already started")
           }
           req := execMsg{
              Command: cmd,
           }
        
           ok, err := s.ch.SendRequest("exec", true, Marshal(&req))           if err == nil && !ok {
              err = fmt.Errorf("ssh: command %v failed", cmd)
           }           if err != nil {              return err
           }           return s.start()
        }

1.2.5 示例代碼(執行命令)

這里我們使用Run()方法來演示一下如果去執行命令,其他方法類型就不做演示了。這里我們使用一個標準輸出流、錯誤流來保存執行結果。

這里演示了一個簡單的執行過程,使用了cd命令到/home/min目錄下,在給helloworld程序添加可執行權限,最后運行程序。

        var stdoutBuf, stderrBuf bytes.Buffer
        session.Stdout = &stdoutBuf
        session.Stderr = &stderrBuf    
        // cd /home/min
        // chmod +x helloworld
        // ./helloworld
        cmd := fmt.Sprintf("cd %v ; chmod +x %v ; %v &", "/home/min", "helloworld", ./helloworld)
        err := session.Run(cmd)        if err != nil {
            log.Fatal("[ERROR]: ", session.Stderr, err)
        }

1.2.6(創建偽終端)

        // 設置Terminal Mode
	modes := ssh.TerminalModes{
		ssh.ECHO:          0,     // 關閉回顯
		ssh.TTY_OP_ISPEED: 14400, // 設置傳輸速率
		ssh.TTY_OP_OSPEED: 14400,
	}    
        // 請求偽終端
	err = session.RequestPty("linux", 32, 160, modes)	if err != nil {
		log.Println(err)		return
	}    
        // 設置輸入輸出
	session.Stdout = os.Stdout
	session.Stdin = os.Stdin
	session.Stderr = os.Stderr
 
	session.Shell() // 啟動shell
	session.Wait()  // 等待退出

1.2.7 完整代碼

//機器平臺信息type Machine struct {
   IP       string
   Port     string
   Username string
   Password string}//建立SSH連接func CreateSSHConn(m *model.Machine) error {   //初始化連接信息
   config := &ssh.ClientConfig{
      User:            m.Username,
      Auth:            []ssh.AuthMethod{ssh.Password(m.Password)},
      HostKeyCallback: ssh.InsecureIgnoreHostKey(),
      Timeout:         10 * time.Second,
   }
   addr := fmt.Sprintf("%v:%v", m.IP, m.Port)   //建立ssh連接
   sshClient, err := ssh.Dial("tcp", addr, config)   if err != nil {
      fmt.Println("unable create ssh conn", err)      return err
   }   defer sshClient.Close()   
   //建立ssh會話
   session, err := sshClient.NewSession()   if err != nil {
      fmt.Println("unable create ssh conn", err)      return err
   }   defer session.Close()   
   
   //執行命令
   var stdoutBuf, stderrBuf bytes.Buffer
   session.Stdout = &stdoutBuf
   session.Stderr = &stderrBuf
   
   cmd := fmt.Sprintf("cd %v ; chmod +x %v ; %v &", "/home/min", "helloworld", ./helloworld)   if err := session.Run(cmd); err != nil {
       log.Fatal("[ERROR]: ", session.Stderr, err)
   }  
   //創建偽終端
   // 設置Terminal Mode
   modes := ssh.TerminalModes{
           ssh.ECHO:          0,     // 關閉回顯
           ssh.TTY_OP_ISPEED: 14400, // 設置傳輸速率
           ssh.TTY_OP_OSPEED: 14400,
   }      
   // 請求偽終端
   err = session.RequestPty("linux", 32, 160, modes)   if err != nil {
           log.Fatal(err)
   }      
   // 設置輸入輸出
   session.Stdout = os.Stdout
   session.Stdin = os.Stdin
   session.Stderr = os.Stderr
   
   session.Shell() // 啟動shell
   session.Wait()  // 等待退出
   
   return err
}

到此,關于“golang怎么實現ssh”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注創新互聯網站,小編會繼續努力為大家帶來更多實用的文章!

網頁名稱:golang怎么實現ssh
地址分享:http://m.kartarina.com/article8/pipiip.html

成都網站建設公司_創新互聯,為您提供用戶體驗響應式網站定制網站手機網站建設標簽優化App設計

廣告

聲明:本網站發布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網站立場,如需處理請聯系客服。電話:028-86922220;郵箱:631063699@qq.com。內容未經允許不得轉載,或轉載時需注明來源: 創新互聯

網站托管運營
主站蜘蛛池模板: 亚洲中文字幕无码爆乳| 亚洲AV无码1区2区久久| 国产成人亚洲综合无码| 色综合久久无码中文字幕| 无遮掩无码h成人av动漫| 亚洲国产综合无码一区| 亚洲AV成人无码网天堂| 亚洲精品色午夜无码专区日韩| av无码免费一区二区三区| WWW久久无码天堂MV| 日韩精品专区AV无码| 久久久精品人妻无码专区不卡| a级毛片无码免费真人久久| 国产午夜无码视频在线观看 | 无码精品A∨在线观看十八禁| 亚洲人成网亚洲欧洲无码| 国产成人无码AV片在线观看 | 亚洲一级特黄大片无码毛片| 91嫩草国产在线无码观看| 亚洲av无码片在线播放| 全免费a级毛片免费看无码| AV大片在线无码永久免费| 无码中文人妻视频2019| 丰满日韩放荡少妇无码视频| heyzo专区无码综合| 精品无码一区二区三区水蜜桃| 极品无码国模国产在线观看| 国产成人无码精品久久久性色| 亚洲av无码乱码在线观看野外| 中文字幕无码视频手机免费看| 无码精品视频一区二区三区| 免费无码H肉动漫在线观看麻豆| 人妻无码人妻有码中文字幕| yy111111电影院少妇影院无码| 无码精品人妻一区二区三区免费| 日韩av片无码一区二区三区不卡| 无码不卡亚洲成?人片| 亚洲精品无码中文久久字幕| 亚洲AV无码片一区二区三区 | 亚洲AV无码一区二区三区久久精品| 6080YYY午夜理论片中无码 |