使用ssh包实现交互式执行远程命令

创建connect

func connect(user, password, host string, port int) (*ssh.Session, error) {
    var (
        auth  []ssh.AuthMethod
        addr  string
        clientConfig *ssh.ClientConfig
        client *ssh.Client
        session *ssh.Session
        err  error
    )
    // get auth method
    auth = make([]ssh.AuthMethod, 0)
    auth = append(auth, ssh.Password(password))

    clientConfig = &ssh.ClientConfig{
        User: user,
        Auth: auth,
        Timeout: 30 * time.Second,
        HostKeyCallback: func(hostname string, remote net.Addr, key ssh.PublicKey) error {
            return nil
        },// 如果没有设置这个,会报错:ssh: must specify HostKeyCallback
    }

    // connet to ssh
    addr = fmt.Sprintf("%s:%d", host, port)

    if client, err = ssh.Dial("tcp", addr, clientConfig); err != nil {
        return nil, err
    }

    // create session
    if session, err = client.NewSession(); err != nil {
        return nil, err
    }

    return session, nil
}

执行命令:

func main() {
    session, err := connect("用户名", "密码", "IP地址", 访问端口)
    if err != nil {
        log.Fatal(err)
    }
    defer session.Close()

    fd := int(os.Stdin.Fd())
    oldState, err := terminal.MakeRaw(fd)
    if err != nil {
        panic(err)
    }
    defer terminal.Restore(fd, oldState)

    // excute command
    session.Stdout = os.Stdout
    session.Stderr = os.Stderr
    session.Stdin = os.Stdin

    termWidth, termHeight, err := terminal.GetSize(fd)
    if err != nil {
        panic(err)
    }

    // Set up terminal modes
    modes := ssh.TerminalModes{
        ssh.ECHO:  1, // enable 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-256color", termHeight, termWidth, modes); err != nil {
        log.Fatal(err)
    }

    session.Run("top")
}

效果:

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注