为了账号安全,请及时绑定邮箱和手机立即绑定

如何在 golang CLI 中在远程机器上执行命令?

如何在 golang CLI 中在远程机器上执行命令?

Go
梦里花落0921 2022-01-17 16:23:08
如何在 golang CLI 中在远程机器上执行命令?我需要编写一个 golang CLI,它可以通过密钥 SSH 到远程机器并执行 shell 命令。此外,我需要能够做到这一点。例如,通过 SSH 连接到一台机器(如云堡垒),然后通过 SSH 连接到另一台内部机器并执行 shell 命令。我(还)没有找到任何例子。
查看完整描述

3 回答

?
开满天机

TA贡献1786条经验 获得超13个赞

"golang.org/x/crypto/ssh"您可以使用该软件包通过 SSH 在远程计算机上运行命令。


这是一个示例函数,演示了在远程机器上运行单个命令并返回输出的简单用法:


//e.g. output, err := remoteRun("root", "MY_IP", "PRIVATE_KEY", "ls")

func remoteRun(user string, addr string, privateKey string, cmd string) (string, error) {

    // privateKey could be read from a file, or retrieved from another storage

    // source, such as the Secret Service / GNOME Keyring

    key, err := ssh.ParsePrivateKey([]byte(privateKey))

    if err != nil {

        return "", err

    }

    // Authentication

    config := &ssh.ClientConfig{

        User: user,

        // https://github.com/golang/go/issues/19767 

        // as clientConfig is non-permissive by default 

        // you can set ssh.InsercureIgnoreHostKey to allow any host 

        HostKeyCallback: ssh.InsecureIgnoreHostKey(),

        Auth: []ssh.AuthMethod{

            ssh.PublicKeys(key),

        },

        //alternatively, you could use a password

        /*

            Auth: []ssh.AuthMethod{

                ssh.Password("PASSWORD"),

            },

        */

    }

    // Connect

    client, err := ssh.Dial("tcp", net.JoinHostPort(addr, "22"), config)

    if err != nil {

        return "", err

    }

    // Create a session. It is one session per command.

    session, err := client.NewSession()

    if err != nil {

        return "", err

    }

    defer session.Close()

    var b bytes.Buffer  // import "bytes"

    session.Stdout = &b // get output

    // you can also pass what gets input to the stdin, allowing you to pipe

    // content from client to server

    //      session.Stdin = bytes.NewBufferString("My input")


    // Finally, run the command

    err = session.Run(cmd)

    return b.String(), err

}


查看完整回答
反对 回复 2022-01-17
?
青春有我

TA贡献1784条经验 获得超8个赞

尝试使用 os/exec https://golang.org/pkg/os/exec/来执行 ssh


package main


import (

    "bytes"

    "log"

    "os/exec"

)


func main() {

    cmd := exec.Command("ssh", "remote-machine", "bash-command")

    var out bytes.Buffer

    cmd.Stdout = &out

    err := cmd.Run()

    if err != nil {

        log.Fatal(err)

    }

}

要跳过机器,请使用 ssh 配置文件中的 ProxyCommand 指令。


Host remote_machine_name

  ProxyCommand ssh -q bastion nc remote_machine_ip 22


查看完整回答
反对 回复 2022-01-17
?
UYOU

TA贡献1878条经验 获得超4个赞

这里的其他解决方案也可以,但我会抛出另一个你可以尝试的选项:simplessh。我认为它更容易使用。对于这个问题,我将使用下面的选项 3,您可以在其中使用您的密钥进行 ssh。


选项 1:使用密码 SSH 到机器,然后运行命令


import (

    "log"


    "github.com/sfreiberg/simplessh"

)


func main() error {

    var client *simplessh.Client

    var err error


    if client, err = simplessh.ConnectWithPassword("hostname_to_ssh_to", "username", "password"); err != nil {

        return err

    }


    defer client.Close()


    // Now run the commands on the remote machine:

    if _, err := client.Exec("cat /tmp/somefile"); err != nil {

        log.Println(err)

    }


    return nil

}

选项 2:使用一组可能的密码通过 SSH 连接到机器,然后运行命令


import (

    "log"


    "github.com/sfreiberg/simplessh"

)


type access struct {

    login    string

    password string

}


var loginAccess []access


func init() {

    // Initialize all password to try

    loginAccess = append(loginAccess, access{"root", "rootpassword1"})

    loginAccess = append(loginAccess, access{"someuser", "newpassword"})

}


func main() error {

    var client *simplessh.Client

    var err error


    // Try to connect with first password, then tried second else fails gracefully

    for _, credentials := range loginAccess {

        if client, err = simplessh.ConnectWithPassword("hostname_to_ssh_to", credentials.login, credentials.password); err == nil {

            break

        }

    }


    if err != nil {

        return err

    }


    defer client.Close()


    // Now run the commands on the remote machine:

    if _, err := client.Exec("cat /tmp/somefile"); err != nil {

        log.Println(err)

    }


    return nil

}

选项 3:使用您的密钥通过 SSH 连接到机器


import (

    "log"


    "github.com/sfreiberg/simplessh"

)


func SshAndRunCommand() error {

    var client *simplessh.Client

    var err error


    // Option A: Using a specific private key path:

    //if client, err = simplessh.ConnectWithKeyFile("hostname_to_ssh_to", "username", "/home/user/.ssh/id_rsa"); err != nil {


    // Option B: Using your default private key at $HOME/.ssh/id_rsa:

    //if client, err = simplessh.ConnectWithKeyFile("hostname_to_ssh_to", "username"); err != nil {


    // Option C: Use the current user to ssh and the default private key file:

    if client, err = simplessh.ConnectWithKeyFile("hostname_to_ssh_to"); err != nil {

        return err

    }


    defer client.Close()


    // Now run the commands on the remote machine:

    if _, err := client.Exec("cat /tmp/somefile"); err != nil {

        log.Println(err)

    }


    return nil

}


查看完整回答
反对 回复 2022-01-17
  • 3 回答
  • 0 关注
  • 163 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信