Go Library to Execute Commands Over SSH at Scale

vSSH

Go library to handle tens of thousands SSH connections and execute the command(s) with higher-level API for building network device / server automation. Documentation and examples are available via godoc.

Test Status Go Report Card Coverage Status GoDoc PkgGoDev

Alt text

Features

  • Connect to multiple remote machines concurrently
  • Persistent SSH connection
  • DSL query based on the labels
  • Manage number of sessions per SSH connection
  • Limit amount of stdout and stderr data in bytes
  • Higher-level API for building automation

Sample query with label

labels := map[string]string {
  "POP" : "LAX",
  "OS" : "JUNOS",
}
// sets labels to a client
vs.AddClient(addr, config, vssh.SetLabels(labels))
// query with label
vs.RunWithLabel(ctx, cmd, timeout, "(POP == LAX || POP == DCA) && OS == JUNOS")

Basic example

vs := vssh.New().Start()
config := vssh.GetConfigUserPass("vssh", "vssh")
for _, addr := range []string{"54.193.17.197:22", "192.168.2.19:22"} {
  vs.AddClient(addr, config, vssh.SetMaxSessions(4))
}
vs.Wait()

ctx, cancel := context.WithCancel(context.Background())
defer cancel()

cmd:= "ping -c 4 192.168.55.10"
timeout, _ := time.ParseDuration("6s")
respChan := vs.Run(ctx, cmd, timeout)

for resp := range respChan {
  if err := resp.Err(); err != nil {
    log.Println(err)
      continue
    }

  outTxt, errTxt, _ := resp.GetText(vs)
  fmt.Println(outTxt, errTxt, resp.ExitStatus())
}

Stream example

vs := vssh.New().Start()
config, _ := vssh.GetConfigPEM("vssh", "mypem.pem")
vs.AddClient("54.193.17.197:22", config, vssh.SetMaxSessions(4))
vs.Wait()

ctx, cancel := context.WithCancel(context.Background())
defer cancel()

cmd:= "ping -c 4 192.168.55.10"
timeout, _ := time.ParseDuration("6s")
respChan := vs.Run(ctx, cmd, timeout)

resp := <- respChan
if err := resp.Err(); err != nil {
  log.Fatal(err)
}

stream := resp.GetStream()
defer stream.Close()

for stream.ScanStdout() {
  txt := stream.TextStdout()
  fmt.Println(txt)
}

Supported platform

  • Linux
  • Windows
  • Darwin
  • BSD
  • Solaris

License

Code is licensed under the Apache License, Version 2.0 (the "License"). Content is licensed under the CC BY 4.0 license. Terms available at https://creativecommons.org/licenses/by/4.0/.

Contribute

Welcomes any kind of contribution, please follow the next steps:

  • Fork the project on github.com.
  • Create a new branch.
  • Commit changes to the new branch.
  • Send a pull request.
Owner
Yahoo
Yahoo is a Verizon Media brand. This organization is the home to many of the active open source projects published by engineers at Yahoo and Verizon Media.
Yahoo
Comments
  • Feature: feed private key from memory

    Feature: feed private key from memory

    Currently vssh.GetConfigPEM() function expects to read the key from a file on disk via: key, err := ioutil.ReadFile(keyFile) but when using vssh as a library it can be not very convenient to generate a new key, write it to disk and then read it from disk again in GetConfigPEM(). Instead it would be great to have the option to generate a private key and feed it directly from memory to either GetConfigPEM() or a similar function like GetConfigFoo(user string, block *pem.Block) or GetConfigFoo(user string, block []byte). Let me know what are your thoughts :)

  • Fix typo in code of conduct section.

    Fix typo in code of conduct section.

    I confirm that this contribution is made under the terms of the license found in the root directory of this repository's source tree and that I have the authority necessary to make this contribution on behalf of its copyright owner.

  • Race condition

    Race condition

    Hello everyone, there seems to be a race condition in the following places:

    WARNING: DATA RACE
    Read at 0x00c00130d650 by goroutine 43:
      github.com/yahoo/vssh.(*VSSH).reConnect()
          go/pkg/mod/github.com/yahoo/[email protected]/vssh.go:369 +0x128
    
    Previous write at 0x00c00130d650 by goroutine 280:
      github.com/yahoo/vssh.(*clientAttr).setErr()
          go/pkg/mod/github.com/yahoo/[email protected]/client.go:314 +0x564
      github.com/yahoo/vssh.(*clientAttr).connect()
          go/pkg/mod/github.com/yahoo/[email protected]/client.go:366 +0x42d
      github.com/yahoo/vssh.(*connect).run()
          go/pkg/mod/github.com/yahoo/[email protected]/client.go:403 +0x228
      github.com/yahoo/vssh.(*VSSH).process.func1()
          go/pkg/mod/github.com/yahoo/[email protected]/vssh.go:223 +0x20e
    
    Goroutine 43 (running) created at:
      github.com/yahoo/vssh.(*VSSH).Start()
          go/pkg/mod/github.com/yahoo/[email protected]/vssh.go:193 +0xbc
    
    Goroutine 280 (running) created at:
      github.com/yahoo/vssh.(*VSSH).process()
          go/pkg/mod/github.com/yahoo/[email protected]/vssh.go:216 +0x64
    ==================
    ==================
    WARNING: DATA RACE
    Read at 0x00c00130d648 by goroutine 43:
      github.com/yahoo/vssh.(*VSSH).reConnect()
          go/pkg/mod/github.com/yahoo/[email protected]/vssh.go:369 +0x32c
    
    Previous write at 0x00c00130d648 by goroutine 280:
      github.com/yahoo/vssh.(*clientAttr).setErr()
          go/pkg/mod/github.com/yahoo/[email protected]/client.go:311 +0x472
      github.com/yahoo/vssh.(*clientAttr).connect()
          go/pkg/mod/github.com/yahoo/[email protected]/client.go:366 +0x42d
      github.com/yahoo/vssh.(*connect).run()
          go/pkg/mod/github.com/yahoo/[email protected]/client.go:403 +0x228
      github.com/yahoo/vssh.(*VSSH).process.func1()
          go/pkg/mod/github.com/yahoo/[email protected]/vssh.go:223 +0x20e
    
    Goroutine 43 (running) created at:
      github.com/yahoo/vssh.(*VSSH).Start()
          go/pkg/mod/github.com/yahoo/[email protected]/vssh.go:193 +0xbc
    
    
    Goroutine 280 (running) created at:
      github.com/yahoo/vssh.(*VSSH).process()
          go/pkg/mod/github.com/yahoo/[email protected]/vssh.go:216 +0x64
    
  • Fix example

    Fix example

    The arguments of example's vssh.GetConfigPEM(user, keyFile string) look different.

    https://godoc.org/github.com/yahoo/vssh#GetConfigPEM

    I confirm that this contribution is made under the terms of the license found in the root directory of this repository's source tree and that I have the authority necessary to make this contribution on behalf of its copyright owner.

  • Empty resp.ID()

    Empty resp.ID()

    Hello, seems like if a response contains an error then resp.ID() produces an empty string.

    for resp := range respChan {
      if err := resp.Err(); err != nil {
        log.Println(resp.ID())
        }
    }
    
  • Race conditions

    Race conditions

    Hello, i just found a couple of race conditions, seems like there could be more given that client write and read happens in multiple places so some access synchronization to this data structure would be needed. Please see below:

    WARNING: DATA RACE
    Write at 0x00c0002024a0 by goroutine 46:
      github.com/yahoo/vssh.(*clientAttr).connect()
          go/pkg/mod/github.com/yahoo/[email protected]/client.go:360 +0x5f7
      github.com/yahoo/vssh.(*connect).run()
          go/pkg/mod/github.com/yahoo/[email protected]/client.go:393 +0x20b
      github.com/yahoo/vssh.(*VSSH).process.func1()
          go/pkg/mod/github.com/yahoo/[email protected]/vssh.go:223 +0x1f1
    
    Previous read at 0x00c0002024a0 by main goroutine:
      github.com/yahoo/vssh.(*VSSH).Wait()
          go/pkg/mod/github.com/yahoo/[email protected]/vssh.go:425 +0xda
    
    Goroutine 46 (running) created at:
      github.com/yahoo/vssh.(*VSSH).process()
          go/pkg/mod/github.com/yahoo/[email protected]/vssh.go:216 +0x64
    ==================
    ==================
    WARNING: DATA RACE
    Read at 0x00c000202690 by goroutine 1104:
      github.com/yahoo/vssh.(*query).run.func1()
          go/pkg/mod/github.com/yahoo/[email protected]/query.go:74 +0xfd
    
    Previous write at 0x00c000202690 by goroutine 48:
      github.com/yahoo/vssh.(*clientAttr).connect()
          go/pkg/mod/github.com/yahoo/[email protected]/client.go:362 +0x69a
      github.com/yahoo/vssh.(*connect).run()
          go/pkg/mod/github.com/yahoo/[email protected]/client.go:393 +0x20b
      github.com/yahoo/vssh.(*VSSH).process.func1()
          go/pkg/mod/github.com/yahoo/[email protected]/vssh.go:223 +0x1f1
    
    Goroutine 1104 (running) created at:
      github.com/yahoo/vssh.(*query).run()
          go/pkg/mod/github.com/yahoo/[email protected]/query.go:63 +0x120
      github.com/yahoo/vssh.(*VSSH).process.func1()
          go/pkg/mod/github.com/yahoo/[email protected]/vssh.go:226 +0x27e
    
    Goroutine 48 (running) created at:
      github.com/yahoo/vssh.(*VSSH).process()
          go/pkg/mod/github.com/yahoo/[email protected]/vssh.go:216 +0x64
    
  • edit comments, trim whitespace

    edit comments, trim whitespace

    PR makes editorial changes to the comments (adding periods to sentences etc.) and truncates trailing whitespace (due to editor settings - will help to avoid such "spurious" diffs in the future).

    I confirm that this contribution is made under the terms of the license found in the root directory of this repository's source tree and that I have the authority necessary to make this contribution on behalf of its copyright owner.

  • correct staticcheck issues

    correct staticcheck issues

    PR contains changes to fix the code issues flagged by staticcheck:

    $ staticcheck ./...
    
    client.go:273:2: should use 'return <expr>' instead of 'if <expr> { return <bool> }; return <bool>' (S1008)
    client.go:501:2: should use a simple channel send/receive instead of select with a single case (S1000)
    client.go:529:2: should use a simple channel send/receive instead of select with a single case (S1000)
    client_test.go:502:2: this value of session is never used (SA4006)
    example_test.go:119:20: session.New is deprecated: Use NewSession functions to create sessions instead. NewSession has the same functionality as New except an error can be returned when the func is called instead of waiting to receive an error until a request is made.  (SA1019)
    example_test.go:139:24: *&x will be simplified to x. It will not copy x. (SA4001)
    vssh.go:51:2: field ctx is unused (U1000)
    vssh.go:60:2: field errors is unused (U1000)
    vssh.go:62:2: field clients is unused (U1000)
    vssh.go:369:19: using time.Tick leaks the underlying ticker, consider using it only in endless functions, tests and the main package, and use time.NewTicker here (SA1015)
    

    I confirm that this contribution is made under the terms of the license found in the root directory of this repository's source tree and that I have the authority necessary to make this contribution on behalf of its copyright owner.

  • Source ip/host?

    Source ip/host?

    In the following code provided in the examples, how to get the client ip/host which generated the outTxt

    	// get the resp channel for each client
    	for resp := range respChan {
    		// in case of the connectivity issue to client
    		if err := resp.Err(); err != nil {
    			log.Println(err)
    			continue
    		}
    
    		// get the returned data from client
    		outTxt, errTxt, err := resp.GetText(vs)
    
  • SetInitNumProc compile error

    SetInitNumProc compile error

    With the following code

            vs := vssh.New()
            vs.SetInitNumProc(2)
            vs.Start()
    

    I am getting the following output command-line-arguments ./main.go:13:4: vs.SetInitNumProc undefined (type *vssh.VSSH has no field or method SetInitNumProc)

  • Bogus example in comment/README.md

    Bogus example in comment/README.md

    The README.md file, and the vssh.go docstring available here both contain the following example:

    vs.RunWithLabel(ctx, cmd, timeout, "POP == LAX || POP == DCA) && OS == JUNOS")

    The expression there is malformed:

    POP == LAX || POP == DCA) && OS == JUNOS

    Notice the closing ), without an opening (.

  • Fix lost chunks during streaming of large volumes of data.

    Fix lost chunks during streaming of large volumes of data.

    The current streaming implementation allows for chunks of data to be lost in VSSH's default select{} cases, if volumes of data arrive at a rate too high to be processed. The default cases get selected when the write channel buffer becomes full and would block. This patch puts a client into a streaming mode when the GetStream() function is called, which causes a blocking select{} to be used until the streaming mode is ended.

    I confirm that this contribution is made under the terms of the license found in the root directory of this repository's source tree and that I have the authority necessary to make this contribution on behalf of its copyright owner.

  • Provide direct access to ssh.Session.StdoutPipe

    Provide direct access to ssh.Session.StdoutPipe

    In situations where one needs to receive large amounts of binary data from a remote server, the only way to do so in vssh is for the remote server to send it in newline-terminated chunks <64k at a time.

    In client.go, ssh.Session.StdoutPipe gets connected to a bufio.Scanner, which is not suitable for binary data since its default buffer is limited to 64k. Ideally there should be a way to directly export ssh.Session.StdoutPipe so that scanning and reading can be left up to the implementation that's using vssh.

Bucket-ssh. A fuzzy ssh manager for managing and categorizing ssh connections.
Bucket-ssh. A fuzzy ssh manager for managing and categorizing ssh connections.

Bssh is an ssh bucket for categorizing and automating ssh connections. Also, with parallel command execution and connection checks(pings) over categories (namespaces).

Oct 25, 2022
A CLI to execute AT Commands via serial port connections.
A CLI to execute AT Commands via serial port connections.

AT Command CLI A CLI to execute AT Commands via serial port connections. Development Install Go Run go run main.go

Dec 13, 2022
GC2 is a Command and Control application that allows an attacker to execute commands on the target machine using Google Sheet and exfiltrate data using Google Drive.
GC2 is a Command and Control application that allows an attacker to execute commands on the target machine using Google Sheet and exfiltrate data using Google Drive.

GC2 GC2 (Google Command and Control) is a Command and Control application that allows an attacker to execute commands on the target machine using Goog

Dec 13, 2022
Slack remote terminal - execute commands on remote host using slack slash command

slackRT Slack remote terminal - execute commands on remote host using slack slash command Installation Go to api.slack.com/apps and sign in and create

Jul 12, 2022
Go package for running Linux distributed shell commands via SSH.
Go package for running Linux distributed shell commands via SSH.

Go package for running Linux distributed shell commands via SSH.

Dec 7, 2022
Terminal based wordle clone. Uses the amazing charm.sh libraries to render and expose the game over SSH

Terminal based wordle clone. Uses the amazing charm.sh libraries to render and expose the game over SSH

Nov 17, 2022
Envp - ENVP is cli wrapper that sets environment variables by profile when you execute the command line

ENVP ENVP is cli wrapper that sets environment variables by profile based config

Nov 7, 2022
Godbolt console wrapper for easily execute local file without any security risk and compiler.

Godbolt CLI Godbolt console wrapper for easily execute local file without any security risk and compiler. Install Compile the source code and add to y

May 22, 2022
Integrated console application library, using Go structs as commands, with menus, completions, hints, history, Vim mode, $EDITOR usage, and more ...
Integrated console application library, using Go structs as commands, with menus, completions, hints, history, Vim mode, $EDITOR usage, and more ...

Gonsole - Integrated Console Application library This package rests on a readline console library, (giving advanced completion, hint, input and histor

Nov 20, 2022
A Go library and common interface for running local and remote commands

go-runcmd go-runcmd is a Go library and common interface for running local and remote commands providing the Runner interface which helps to abstract

Nov 25, 2021
🧑‍💻📊 Show off your most used shell commands
🧑‍💻📊 Show off your most used shell commands

tsukae ??‍?? ?? Tsukae, 使え - means use in Japanese (so it refers to commands that you use) Built on top of termui and cobra Big shoutout to jokerj40 f

Dec 17, 2022
cTRL is a server for remote execution of pending tasks and commands in real time, supporting a queue with continuous thread limiting and throttling.

Документация на русском: https://github.com/eltaline/ctrl/blob/master/README-RUS.md cTRL is a server written in Go language that uses a modified versi

Mar 3, 2022
Tool for shell commands execution, visualization and alerting. Configured with a simple YAML file.
Tool for shell commands execution, visualization and alerting. Configured with a simple YAML file.

Sampler. Visualization for any shell command. Sampler is a tool for shell commands execution, visualization and alerting. Configured with a simple YAM

Dec 28, 2022
miscellaneous useful commands, including 'gosh' the Go scripting tool

utilities Miscellaneous useful commands. gosh This is a tool for running Go code from the command line. See here. findCmpRm This finds files with copi

Oct 31, 2022
ag is a tool for defining an alias for a group of commands

AG Introduction ag is a command line tool that similar to Makefile. with ag you can make an alias for group of commands with custom flags. This tool i

Jul 17, 2022
Commando - run commands against networking devices in batch mode
Commando - run commands against networking devices in batch mode

Commando is a tiny tool that enables users to collect command outputs from a single or a multiple networking devices defined in an inventory file.

Oct 30, 2022
Brigodier is a command parser & dispatcher, designed and developed for command lines such as for Discord bots or Minecraft chat commands. It is a complete port from Mojang's "brigadier" into Go.

brigodier Brigodier is a command parser & dispatcher, designed and developed to provide a simple and flexible command framework. It can be used in man

Dec 15, 2022
Command-line tool to load csv and excel (xlsx) files and run sql commands
Command-line tool to load csv and excel (xlsx) files and run sql commands

csv-sql supports loading and saving results as CSV and XLSX files with data processing with SQLite compatible sql commands including joins.

Nov 2, 2022
webify - Turn functions and commands into web services
webify - Turn functions and commands into web services

webify is a very basic CGI server which forwards all requests to a single script. A design goal is to be as zero-config as possible.

Dec 22, 2022