Golang笔记:使用ssh包作为客户端与SSH服务器交互

目的

Golang中可以使用 golang.org/x/crypto/ssh 包作为SSH客户端或者SSH服务使用。这篇文章将简单记录下作为客户端使用的一些内容。

Package ssh implements an SSH client and server.

基础说明

作为客户端与SSH服务器操作上来说主要分为三步:

  • 使用一定的参数与SSH服务器建立连接得到 Client 对象;
  • Client 之上建立会话 Session ,设置会话的输入输出等配置;
  • 通过 Session 进行单次或是连续通讯;

使用演示

单次通讯

SessionRun Output CombinedOutput 方法都可用于单次通讯,下面是个简单的演示:

package main

import (
	"bytes"
	"fmt"
	"log"

	"golang.org/x/crypto/ssh"
)

func main() {
	// 设置客户端请求参数
	// var hostKey ssh.PublicKey
	config := &ssh.ClientConfig{
		User: "root",
		Auth: []ssh.AuthMethod{
			ssh.Password("naisu233"),
		},
		// HostKeyCallback: ssh.FixedHostKey(hostKey),
		HostKeyCallback: ssh.InsecureIgnoreHostKey(), // 忽略主机密钥
	}

	// 作为客户端连接SSH服务器
	client, err := ssh.Dial("tcp", "192.168.31.142:22", 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()

	// 设置会话标准输出,运行命令
	var b bytes.Buffer
	session.Stdout = &b
	if err := session.Run("cat /proc/cpuinfo"); err != nil {
		log.Fatal("Failed to run: " + err.Error())
	}

	fmt.Println(b.String())
}

在这里插入图片描述

需要注意的是每个 Session 只能进行一次通讯,并且上述的几个方法通讯时会阻塞。另外需要注意的是这几个方法只会在指令运行结束时才会返回结果,不适合用在持续进行的命令中(比如 top 命令)。

连续通讯(远程终端)

连续通讯只要使用 SessionStart Shell 方法,使用这两者时需要使用 Wait 方法来等待结束会话。 Shell 方法可以作为远程终端使用:

package main

import (
	"log"
	"os"

	"golang.org/x/crypto/ssh"
	"golang.org/x/term"
)

func main() {
	// 设置客户端请求参数
	// var hostKey ssh.PublicKey
	config := &ssh.ClientConfig{
		User: "root",
		Auth: []ssh.AuthMethod{
			ssh.Password("naisu233"),
		},
		// HostKeyCallback: ssh.FixedHostKey(hostKey),
		HostKeyCallback: ssh.InsecureIgnoreHostKey(), // 忽略主机密钥
	}

	// 作为客户端连接SSH服务器
	conn, err := ssh.Dial("tcp", "192.168.31.142:22", config)
	if err != nil {
		log.Fatal("unable to connect: ", err)
	}
	defer conn.Close()

	// 创建会话
	session, err := conn.NewSession()
	if err != nil {
		log.Fatal("unable to create session: ", err)
	}
	defer session.Close()

	// 设置会话的标准输出、错误输出、标准输入
	session.Stdout = os.Stdout
	session.Stderr = os.Stderr
	session.Stdin = os.Stdin

	// 设置终端参数
	modes := ssh.TerminalModes{
		ssh.ECHO:          0,     // disable echoing
		ssh.TTY_OP_ISPEED: 14400, // input speed = 14.4kbaud
		ssh.TTY_OP_OSPEED: 14400, // output speed = 14.4kbaud
	}

	termWidth, termHeight, err := term.GetSize(int(os.Stdout.Fd())) // 获取当前标准输出终端窗口尺寸 // 该操作可能有的平台上不可用,那么下面手动指定终端尺寸即可
	if err != nil {
		log.Fatal("unable to terminal.GetSize: ", err)
	}

	// 设置虚拟终端与远程会话关联
	if err := session.RequestPty("xterm", termHeight, termWidth, modes); err != nil {
		log.Fatal("request for pseudo terminal failed: ", err)
	}

	// 启动远程Shell
	if err := session.Shell(); err != nil {
		log.Fatal("failed to start shell: ", err)
	}

	// 阻塞直至结束会话
	if err := session.Wait(); err != nil {
		log.Fatal("exit error: ", err)
	}
}

在这里插入图片描述

总结

Golang作为客户端与SSH服务器交互还是比较方便的,实际使用中更多的需要注意阻塞方法以及持续执行的外部程序的处理。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Naisu Xu

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值