How do I execute a command on a remote machine in a golang CLI?

前端 未结 4 1183
臣服心动
臣服心动 2021-02-13 07:02

How do I execute a command on a remote machine in a golang CLI? I need to write a golang CLI that can SSH into a remote machine via a key and execute a shell command. Furthermor

相关标签:
4条回答
  • 2021-02-13 07:24

    Try the package https://github.com/appleboy/easyssh-proxy

    package main
    
    import (
        "fmt"
        "time"
    
        "github.com/appleboy/easyssh-proxy"
    )
    
    func main() {
        // Create MakeConfig instance with remote username, server address and path to private key.
        ssh := &easyssh.MakeConfig{
            User:   "appleboy",
            Server: "example.com",
            // Optional key or Password without either we try to contact your agent SOCKET
            //Password: "password",
            // Paste your source content of private key
            // Key: `-----BEGIN RSA PRIVATE KEY-----
            // MIIEpAIBAAKCAQEA4e2D/qPN08pzTac+a8ZmlP1ziJOXk45CynMPtva0rtK/RB26
            // 7XC9wlRna4b3Ln8ew3q1ZcBjXwD4ppbTlmwAfQIaZTGJUgQbdsO9YA==
            // -----END RSA PRIVATE KEY-----
            // `,
            KeyPath: "/Users/username/.ssh/id_rsa",
            Port:    "22",
            Timeout: 60 * time.Second,
        }
    
        // Call Run method with command you want to run on remote server.
        stdout, stderr, done, err := ssh.Run("ls -al", 60*time.Second)
        // Handle errors
        if err != nil {
            panic("Can't run remote command: " + err.Error())
        } else {
            fmt.Println("don is :", done, "stdout is :", stdout, ";   stderr is :", stderr)
        }
    
    }
    

    See more example.

    0 讨论(0)
  • 2021-02-13 07:30

    You can run commands on a remote machine over SSH using the "golang.org/x/crypto/ssh" package.

    Here is an example function demonstrating simple usage of running a single command on a remote machine and returning the output:

    //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,
            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
    }
    
    0 讨论(0)
  • 2021-02-13 07:43

    Try with os/exec https://golang.org/pkg/os/exec/ to execute a 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)
        }
    }
    

    To jump over machines use the ProxyCommand directive in a ssh config file.

    Host remote_machine_name
      ProxyCommand ssh -q bastion nc remote_machine_ip 22
    
    0 讨论(0)
  • 2021-02-13 07:44

    The other solutions here will work, but I'll throw out another option you could try: simplessh. I think it is easier to use. For this question, I would use option 3 below where you can ssh using your key.

    Option 1: SSH to a machine with a password, then run a command

    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
    }
    

    Option 2: SSH to a machine using a set of possible passwords, then run a command

    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
    }
    

    Option 3: SSH to a machine using your key

    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
    }
    
    0 讨论(0)
提交回复
热议问题