Categorygithub.com/odemakov/sshrun
repositorypackage
0.0.5
Repository: https://github.com/odemakov/sshrun.git
Documentation: pkg.go.dev

# README

sshrun

sshrun is a simple package that implements an SSH connection pool, allowing users to run commands concurrently up to the server's SSHD MaxSessions limit. It opens a single connection to the host and reuses it for multiple sessions, optimizing resource usage and connection management. The package also provides a debug mode to log detailed debug messages, aiding in troubleshooting and performance monitoring.

Usage example

package main

import (
	"log"
	"os"
	"path/filepath"
	"sync"

	"github.com/odemakov/sshrun"
)

func main() {
    // get home directory of current user
    homeDir, err := os.UserHomeDir()
    if err != nil {
        log.Fatalf("Failed to get home directory: %v", err)
    }

    runCfg := &sshrun.RunConfig{
        Debug: false,
        PrivateKey: filepath.Join(homeDir, ".ssh", "id_rsa"),
    }
    sshPool := sshrun.NewPool(runCfg)

    sshCfg := &sshrun.SSHConfig{
        User: "mak",
        Host: "dev-02",
    }

    // Exec 15 concurrent commands. Default MaxSessions value for the SSHD server is 10, so
    // with 15 workers, 5 of them will fail.
    var wg sync.WaitGroup
    for i := 0; i < 100; i++ {
        log.Printf("Running command in loop %d", i)
        //result, err := sshPool.Run(sshCfg, "for i in {1..100}; do echo $i; sleep 1; done",
        result, err := sshPool.Run(sshCfg, "uptime",
            func(stdout string) {
                log.Printf("Loop %d - Stdout: %s", i, stdout)
            },
            func(stderr string) {
                log.Printf("Loop %d - Stderr: %s", i, stderr)
            })
        if err != nil {
            switch e := err.(type) {
            case *sshrun.SSHError:
                log.Printf("Loop %d - SSH error: %s", i, e.Msg)
            case *sshrun.CommandError:
                log.Printf("Loop %d - Command error: %s", i, e.Msg)
            default:
                log.Printf("Loop %d - Unknown error: %v", i, err)
            }
        } else {
            log.Printf("Loop %d - Error code: %d", i, result)
        }
    }
    wg.Wait()

    sshPool.ClosePool()
}