Process Golang从终端进程写入输入并获取输出

Process Golang从终端进程写入输入并获取输出,process,terminal,go,pty,Process,Terminal,Go,Pty,我有一个关于如何从终端子进程(如ssh)发送输入和接收输出的问题。python中的一个示例如下: 我在Golang找不到一个简单的例子,与上面的工作原理类似 在Golang,我想做类似的事情,但似乎不起作用: cmd := exec.Command("ssh", "user@x.x.x.x") cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr stdin, _ := cmd.StdinPipe() stdin.W

我有一个关于如何从终端子进程(如ssh)发送输入和接收输出的问题。python中的一个示例如下:

我在Golang找不到一个简单的例子,与上面的工作原理类似

在Golang,我想做类似的事情,但似乎不起作用:

    cmd := exec.Command("ssh", "user@x.x.x.x")
    cmd.Stdout = os.Stdout
    cmd.Stderr = os.Stderr
    stdin, _ := cmd.StdinPipe()
    stdin.Write([]byte("password\n"))
    cmd.Run()
但是,;我不知道如何在go中执行此操作,因为每次执行此ssh命令时,我只能获得输出。我无法从密码中自动输入密码。
有人有向终端进程(如ssh)写入数据的例子吗?如果是,请分享

多亏了上面的评论,我才能够使用密码获得ssh访问权限。我使用了golang的SSHAPI库。这相当简单,因为我遵循以下示例:

具体而言:

func ExampleDial() {
    // An SSH client is represented with a ClientConn. Currently only
    // the "password" authentication method is supported.
    //
    // To authenticate with the remote server you must pass at least one
    // implementation of AuthMethod via the Auth field in ClientConfig.
    config := &ClientConfig{
            User: "username",
            Auth: []AuthMethod{
                    Password("yourpassword"),
            },
    }
    client, err := Dial("tcp", "yourserver.com:22", config)
    if err != nil {
            panic("Failed to dial: " + err.Error())
    }

    // Each ClientConn can support multiple interactive sessions,
    // represented by a Session.
    session, err := client.NewSession()
    if err != nil {
            panic("Failed to create session: " + err.Error())
    }
    defer session.Close()

    // Once a Session is created, you can execute a single command on
    // the remote side using the Run method.
    var b bytes.Buffer
    session.Stdout = &b
    if err := session.Run("/usr/bin/whoami"); err != nil {
            panic("Failed to run: " + err.Error())
    }
    fmt.Println(b.String())
}

由于上面的评论,我能够使用密码获得ssh访问权限。我使用了golang的SSHAPI库。这相当简单,因为我遵循以下示例:

具体而言:

func ExampleDial() {
    // An SSH client is represented with a ClientConn. Currently only
    // the "password" authentication method is supported.
    //
    // To authenticate with the remote server you must pass at least one
    // implementation of AuthMethod via the Auth field in ClientConfig.
    config := &ClientConfig{
            User: "username",
            Auth: []AuthMethod{
                    Password("yourpassword"),
            },
    }
    client, err := Dial("tcp", "yourserver.com:22", config)
    if err != nil {
            panic("Failed to dial: " + err.Error())
    }

    // Each ClientConn can support multiple interactive sessions,
    // represented by a Session.
    session, err := client.NewSession()
    if err != nil {
            panic("Failed to create session: " + err.Error())
    }
    defer session.Close()

    // Once a Session is created, you can execute a single command on
    // the remote side using the Run method.
    var b bytes.Buffer
    session.Stdout = &b
    if err := session.Run("/usr/bin/whoami"); err != nil {
            panic("Failed to run: " + err.Error())
    }
    fmt.Println(b.String())
}

这是上述示例的修改/完整版本

首先获取
终端
包,通过
获取golang.org/x/crypto/ssh

package main

import (
    "bufio"
    "bytes"
    "fmt"
    "os"
    "strings"

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

func main() {
    if len(os.Args) < 3 {
        usage := "\n./remote-ssh {host} {port}"
        fmt.Println(usage)
    } else {
        host := os.Args[1]
        port := os.Args[2]

        username, password := credentials()
        config := &ssh.ClientConfig{
            User: username,
            Auth: []ssh.AuthMethod{
                ssh.Password(password),
            },
        }
        connectingMsg := fmt.Sprintf("\nConnecting to %s:%v remote server...", host, port)
        fmt.Println(connectingMsg)

        hostAddress := strings.Join([]string{host, port}, ":")
        // fmt.Println("Host add %s ", hostAddress)
        client, err := ssh.Dial("tcp", hostAddress, config)
        if err != nil {
            panic("Failed to dial: " + err.Error())
        }

        for {
            session, err := client.NewSession()
            if err != nil {
                panic("Failed to create session: " + err.Error())
            }
            defer session.Close()

            // Once a Session is created, can execute a single command on remote side
            var cmd string
            str := "\nEnter command (e.g. /usr/bin/whoami OR enter 'exit' to return) : "
            fmt.Print(str)
            fmt.Scanf("%s", &cmd)
            if cmd == "exit" || cmd == "EXIT" {
                break
            }
            s := fmt.Sprintf("Wait for command '%s' run and response...", cmd)
            fmt.Println(s)

            var b bytes.Buffer
            session.Stdout = &b
            if err := session.Run(cmd); err != nil {
                panic("Failed to run: " + err.Error())
            }
            fmt.Println(b.String())
        }
    }
}

func credentials() (string, string) {
    reader := bufio.NewReader(os.Stdin)

    fmt.Print("Enter Username: ")
    username, _ := reader.ReadString('\n')

    fmt.Print("Enter Password: ")
    bytePassword, err := terminal.ReadPassword(0)
    if err != nil {
        panic(err)
    }
    password := string(bytePassword)

    return strings.TrimSpace(username), strings.TrimSpace(password)
}
主程序包
进口(
“布菲奥”
“字节”
“fmt”
“操作系统”
“字符串”
“golang.org/x/crypto/ssh”
“golang.org/x/crypto/ssh/terminal”
)
func main(){
如果len(os.Args)<3{
用法:=“\n./远程ssh{host}{port}”
fmt.Println(使用)
}否则{
主机:=os.Args[1]
端口:=os.Args[2]
用户名、密码:=凭据()
config:=&ssh.ClientConfig{
用户:用户名,
Auth:[]ssh.AuthMethod{
ssh.Password(密码),
},
}
ConnectionMsg:=fmt.Sprintf(“\n正在连接到%s:%v远程服务器…”,主机,端口)
fmt.Println(连接消息)
主机地址:=strings.Join([]字符串{host,port},“:”)
//fmt.Println(“主机添加%s”,主机地址)
客户端,错误:=ssh.Dial(“tcp”,主机地址,配置)
如果错误!=零{
死机(“拨号失败:+err.Error())
}
为了{
会话,错误:=client.NewSession()
如果错误!=零{
死机(“创建会话失败:+err.Error())
}
延迟会话。关闭()
//一旦创建了会话,您就可以在远程端执行单个命令
var cmd字符串
str:=“\n输入命令(例如/usr/bin/whoami或输入'exit'返回):”
格式打印(str)
格式扫描(“%s”和cmd)
如果cmd==“退出”| | cmd==“退出”{
打破
}
s:=fmt.Sprintf(“等待命令“%s”运行并响应…”,cmd)
fmt.Println(s)
VARBytes.Buffer
session.Stdout=&b
如果错误:=session.Run(cmd);错误!=nil{
死机(“无法运行:+err.Error())
}
fmt.Println(b.String())
}
}
}
func凭据()(字符串,字符串){
reader:=bufio.NewReader(os.Stdin)
打印(“输入用户名:”)
用户名:=reader.ReadString('\n')
打印(“输入密码:”)
bytePassword,错误:=终端。读取密码(0)
如果错误!=零{
恐慌(错误)
}
密码:=字符串(bytePassword)
返回strings.TrimSpace(用户名),strings.TrimSpace(密码)
}

这是上述示例的修改/完整版本

首先获取
终端
包,通过
获取golang.org/x/crypto/ssh

package main

import (
    "bufio"
    "bytes"
    "fmt"
    "os"
    "strings"

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

func main() {
    if len(os.Args) < 3 {
        usage := "\n./remote-ssh {host} {port}"
        fmt.Println(usage)
    } else {
        host := os.Args[1]
        port := os.Args[2]

        username, password := credentials()
        config := &ssh.ClientConfig{
            User: username,
            Auth: []ssh.AuthMethod{
                ssh.Password(password),
            },
        }
        connectingMsg := fmt.Sprintf("\nConnecting to %s:%v remote server...", host, port)
        fmt.Println(connectingMsg)

        hostAddress := strings.Join([]string{host, port}, ":")
        // fmt.Println("Host add %s ", hostAddress)
        client, err := ssh.Dial("tcp", hostAddress, config)
        if err != nil {
            panic("Failed to dial: " + err.Error())
        }

        for {
            session, err := client.NewSession()
            if err != nil {
                panic("Failed to create session: " + err.Error())
            }
            defer session.Close()

            // Once a Session is created, can execute a single command on remote side
            var cmd string
            str := "\nEnter command (e.g. /usr/bin/whoami OR enter 'exit' to return) : "
            fmt.Print(str)
            fmt.Scanf("%s", &cmd)
            if cmd == "exit" || cmd == "EXIT" {
                break
            }
            s := fmt.Sprintf("Wait for command '%s' run and response...", cmd)
            fmt.Println(s)

            var b bytes.Buffer
            session.Stdout = &b
            if err := session.Run(cmd); err != nil {
                panic("Failed to run: " + err.Error())
            }
            fmt.Println(b.String())
        }
    }
}

func credentials() (string, string) {
    reader := bufio.NewReader(os.Stdin)

    fmt.Print("Enter Username: ")
    username, _ := reader.ReadString('\n')

    fmt.Print("Enter Password: ")
    bytePassword, err := terminal.ReadPassword(0)
    if err != nil {
        panic(err)
    }
    password := string(bytePassword)

    return strings.TrimSpace(username), strings.TrimSpace(password)
}
主程序包
进口(
“布菲奥”
“字节”
“fmt”
“操作系统”
“字符串”
“golang.org/x/crypto/ssh”
“golang.org/x/crypto/ssh/terminal”
)
func main(){
如果len(os.Args)<3{
用法:=“\n./远程ssh{host}{port}”
fmt.Println(使用)
}否则{
主机:=os.Args[1]
端口:=os.Args[2]
用户名、密码:=凭据()
config:=&ssh.ClientConfig{
用户:用户名,
Auth:[]ssh.AuthMethod{
ssh.Password(密码),
},
}
ConnectionMsg:=fmt.Sprintf(“\n正在连接到%s:%v远程服务器…”,主机,端口)
fmt.Println(连接消息)
主机地址:=strings.Join([]字符串{host,port},“:”)
//fmt.Println(“主机添加%s”,主机地址)
客户端,错误:=ssh.Dial(“tcp”,主机地址,配置)
如果错误!=零{
死机(“拨号失败:+err.Error())
}
为了{
会话,错误:=client.NewSession()
如果错误!=零{
死机(“创建会话失败:+err.Error())
}
延迟会话。关闭()
//一旦创建了会话,您就可以在远程端执行单个命令
var cmd字符串
str:=“\n输入命令(例如/usr/bin/whoami或输入'exit'返回):”
格式打印(str)
格式扫描(“%s”和cmd)
如果cmd==“退出”| | cmd==“退出”{
打破
}
s:=fmt.Sprintf(“等待命令“%s”运行并响应…”,cmd)
fmt.Println(s)
VARBytes.Buffer
session.Stdout=&b
如果错误:=session.Run(cmd);错误!=nil{
死机(“无法运行:+err.Error())
}
fmt.Println(b.String())
}
}
}
func凭据()(字符串,字符串){
reader:=bufio.NewReader(os.Stdin)
打印(“输入用户名:”)
用户名:=reader.ReadString('\n')
打印(“输入密码:”)
bytePassword,错误:=终端。读取密码(0)
如果错误!=零{
恐慌(错误)
}
密码:=字符串(bytePassword)
返回strings.TrimSpace(用户名),strings.TrimSpace(密码)
}

使用
ssh
您无法轻松做到这一点,因为它将拒绝从
stdin