Skip to content

Instantly share code, notes, and snippets.

@iamralch
Last active September 10, 2025 02:55
Show Gist options
  • Save iamralch/b7f56afc966a6b6ac2fc to your computer and use it in GitHub Desktop.
Save iamralch/b7f56afc966a6b6ac2fc to your computer and use it in GitHub Desktop.

Revisions

  1. iamralch revised this gist Jul 20, 2015. 1 changed file with 2 additions and 2 deletions.
    4 changes: 2 additions & 2 deletions ssh_client.go
    Original file line number Diff line number Diff line change
    @@ -35,9 +35,9 @@ func (client *SSHClient) RunCommand(cmd *SSHCommand) error {
    if session, err = client.newSession(); err != nil {
    return err
    }

    defer session.Close()

    if err = client.prepareCommand(session, cmd); err != nil {
    session.Close()
    return err
    }

  2. iamralch created this gist Jul 18, 2015.
    160 changes: 160 additions & 0 deletions ssh_client.go
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,160 @@
    package main

    import (
    "fmt"
    "io"
    "io/ioutil"
    "net"
    "os"
    "strings"

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

    type SSHCommand struct {
    Path string
    Env []string
    Stdin io.Reader
    Stdout io.Writer
    Stderr io.Writer
    }

    type SSHClient struct {
    Config *ssh.ClientConfig
    Host string
    Port int
    }

    func (client *SSHClient) RunCommand(cmd *SSHCommand) error {
    var (
    session *ssh.Session
    err error
    )

    if session, err = client.newSession(); err != nil {
    return err
    }

    if err = client.prepareCommand(session, cmd); err != nil {
    session.Close()
    return err
    }

    err = session.Run(cmd.Path)
    return err
    }

    func (client *SSHClient) prepareCommand(session *ssh.Session, cmd *SSHCommand) error {
    for _, env := range cmd.Env {
    variable := strings.Split(env, "=")
    if len(variable) != 2 {
    continue
    }

    if err := session.Setenv(variable[0], variable[1]); err != nil {
    return err
    }
    }

    if cmd.Stdin != nil {
    stdin, err := session.StdinPipe()
    if err != nil {
    return fmt.Errorf("Unable to setup stdin for session: %v", err)
    }
    go io.Copy(stdin, cmd.Stdin)
    }

    if cmd.Stdout != nil {
    stdout, err := session.StdoutPipe()
    if err != nil {
    return fmt.Errorf("Unable to setup stdout for session: %v", err)
    }
    go io.Copy(cmd.Stdout, stdout)
    }

    if cmd.Stderr != nil {
    stderr, err := session.StderrPipe()
    if err != nil {
    return fmt.Errorf("Unable to setup stderr for session: %v", err)
    }
    go io.Copy(cmd.Stderr, stderr)
    }

    return nil
    }

    func (client *SSHClient) newSession() (*ssh.Session, error) {
    connection, err := ssh.Dial("tcp", fmt.Sprintf("%s:%d", client.Host, client.Port), client.Config)
    if err != nil {
    return nil, fmt.Errorf("Failed to dial: %s", err)
    }

    session, err := connection.NewSession()
    if err != nil {
    return nil, fmt.Errorf("Failed to create session: %s", err)
    }

    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
    }

    if err := session.RequestPty("xterm", 80, 40, modes); err != nil {
    session.Close()
    return nil, fmt.Errorf("request for pseudo terminal failed: %s", err)
    }

    return session, nil
    }

    func PublicKeyFile(file string) ssh.AuthMethod {
    buffer, err := ioutil.ReadFile(file)
    if err != nil {
    return nil
    }

    key, err := ssh.ParsePrivateKey(buffer)
    if err != nil {
    return nil
    }
    return ssh.PublicKeys(key)
    }

    func SSHAgent() ssh.AuthMethod {
    if sshAgent, err := net.Dial("unix", os.Getenv("SSH_AUTH_SOCK")); err == nil {
    return ssh.PublicKeysCallback(agent.NewClient(sshAgent).Signers)
    }
    return nil
    }

    func main() {
    // ssh.Password("your_password")
    sshConfig := &ssh.ClientConfig{
    User: "jsmith",
    Auth: []ssh.AuthMethod{
    SSHAgent(),
    },
    }

    client := &SSHClient{
    Config: sshConfig,
    Host: "example.com",
    Port: 22,
    }

    cmd := &SSHCommand{
    Path: "ls -l $LC_DIR",
    Env: []string{"LC_DIR=/"},
    Stdin: os.Stdin,
    Stdout: os.Stdout,
    Stderr: os.Stderr,
    }

    fmt.Printf("Running command: %s\n", cmd.Path)
    if err := client.RunCommand(cmd); err != nil {
    fmt.Fprintf(os.Stderr, "command run error: %s\n", err)
    os.Exit(1)
    }
    }