用Go写一个轻量级的ssh批量操作工具的方法

2020-01-28 12:54:35丽君

配置的参数照搬 GoDoc 上的示例就好了:


// Set up terminal modes
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
}
// Request pseudo terminal
if err := session.RequestPty("xterm", 40, 80, modes); err != nil {
  log.Fatal("request for pseudo terminal failed: ", err)
}

执行命令

建立起 session 后,执行命令就很简单了,用 session.Run() 就可以执行我们的命令,结果则返回到 session.Studout 里。我们跑个简单的测试。


const (
  username = "admin"
  password = "password"
  ip    = "192.168.15.101"
  port   = 22
  cmd   = "show clock"
)

func Test_SSH_run(t *testing.T) {
  ciphers := []string{}
  session, err := connect(username, password, ip, port, ciphers)
  if err != nil {
    t.Error(err)
    return
  }
  defer session.Close()
  var stdoutBuf bytes.Buffer
  session.Stdout = &stdoutBuf
  session.Run(cmd)
  t.Log(session.Stdout)
  return
}

目标是一台交换机,测试一下


=== RUN  Test_SSH_run
--- PASS: Test_SSH_run (0.69s)
  ssh_test.go:30: 07:55:52.598 UTC Wed Jan 17 2018
PASS

可以看到 show clock 的命令已经成功执行了,并返回了结果。

session.Run() 仅限定执行单条命令,要执行若干命令组合就需要用到 session.Shell() 了。意思很明确,就是模拟一个终端去一条一条执行命令,并返回结果。就像我们用 Shell 一样,我们把整过过程打印出来输出就好了。从 session.StdinPipe() 逐个输入命令,从session.Stdout 和 session.Stderr 获取 Shell 上的输出。一样来做个测试。


const (
  username = "admin"
  password = "password"
  ip    = "192.168.15.101"
  port   = 22
  cmds   = "show clock;show env power;exit"
)
func Test_SSH(t *testing.T) {
  var cipherList []string
  session, err := connect(username, password, ip, key, port, cipherList)
  if err != nil {
    t.Error(err)
    return
  }
  defer session.Close()

  cmdlist := strings.Split(cmd, ";")
  stdinBuf, err := session.StdinPipe()
  if err != nil {
    t.Error(err)
    return
  }

  var outbt, errbt bytes.Buffer
  session.Stdout = &outbt

  session.Stderr = &errbt
  err = session.Shell()
  if err != nil {
    t.Error(err)
    return
  }
  for _, c := range cmdlist {
    c = c + "n"
    stdinBuf.Write([]byte(c))

  }
  session.Wait()
  t.Log((outbt.String() + errbt.String()))
  return
}

还是那台交换机,测试一下


=== RUN  Test_SSH
--- PASS: Test_SSH (0.69s)
  ssh_test.go:51: sw-1#show clock
    07:59:52.598 UTC Wed Jan 17 2018
    sw-1#show env power
    SW PID         Serial#   Status      Sys Pwr PoE Pwr Watts
    -- ------------------ ---------- --------------- ------- ------- -----
     1 Built-in                     Good
    
    sw-1#exit
PASS