Giter VIP home page Giter VIP logo

spawning's Introduction

The spawning package provides a handy API for spawning shell commands on UNIXish environments.

Installation

I suggest the use of glide for managing your Go deps, but you should be able to install it directly without much issue:

go get github.com/ess/spawning

As mentioned, though, a better idea is to use glide (or another package manager that supports SemVer).

Usage

Commands (run via bash -c) can be spawned in a one-off manner, or one can add a collection of commands to a Pool, then run the pool either sequentially, concurrently, or with a custom Runner.

Spawning One-off Commands

Running a one-off command is pretty easy, really:

package main

import (
	"fmt"

	"github.com/ess/spawning"
)

func main() {
	result := spawning.Run("echo 'My sausages turned to gold!'")

	if result.Success {
		fmt.Println("The sausages were successfully turned to gold.")
	}
}

Spawning Multiple Commands

Running multiple commands is fairly easy, too, and you can execute them either Sequentially, Concurrently, or with a custom Runner implementation.

Sequentially

Effectively, the sequential runner could be used to create minimal shell scripts. The important caveat there is that as every command is executed via bash -c, there is no shared environment between the commands in a given Pool.

package main

import (
	"fmt"
	"github.com/ess/spawning"
)

func main() {
	script := spawning.NewPool()
	script.Add("mkdir -p output")
	script.Add("date > output/begin")
	script.Add(`echo "The operation has succeeded" > output/result`)
	script.Add("date > output/end")
	script.Add(`for step in begin result end ; do cat output/${step} ; done`)

	// Run the commands sequentially and process the results
	for _, result := range script.Run(spawning.Sequentially()) {
		processResult(result)
	}
}

func processResult(result *spawning.Result) {
	if !result.Success {
		fmt.Println("The following command failed:", result.Command)
		return
	}

	fmt.Println(result.Output)
}

Concurrently

Running commands concurrently isn't at all great for running locally, but it is quite handy for, say, controlling a cluster via SSH.

package main

import (
	"fmt"
	"github.com/ess/spawning"
)

func main() {

	logins := []string{
		"[email protected]",
		"[email protected]",
		"[email protected]",
		"[email protected]",
	}

	pool := spawning.NewPool()

	for _, login := range logins {
		pool.Add(sshCommand(login, "date"))
	}

	// Run the commands concurrently and process the results
	for _, result := range pool.Run(spawning.Concurrently()) {
		processResult(result)
	}
}

func processResult(result *spawning.Result) {
	if !result.Success {
		fmt.Println("The following command failed:", result.Command)
		return
	}

	fmt.Println(result.Output)
}

func sshCommand(login string, command string) string {
	return fmt.Sprintf("ssh %s '$s'", login, command)
}

Running With A Custom Runner

spawning.Pool's Run() method requires that one pass in a Runner. If neither Sequentially nor Concurrently are suitable for your purposes, you can implement your own Runner:

package main

import (
	"fmt"
	"github.com/ess/spawning"
)

type RoadRunner struct{}

func (runner *RoadRunner) Run(commands []string) []*spawning.Result {
	results := make([]*spawning.Result, 0)

	for _, command := range commands {
		results = append(
			results,
			&spawning.Result{Command: command, Output: "meep meep", Success: true},
		)
	}

	return results
}

func main() {
  runner := &RoadRunner{}

	for _, result := range spawning.NewPool().Add("sudo ls -lah /").Run(runner) {
		processResult(result)
	}
}

func processResult(result *spawning.Result) {
	if !result.Success {
		fmt.Println("The following command failed:", result.Command)
		return
	}

	fmt.Println(result.Output)
}

History

  • v0.1.1 - I'm a jerk that forgets to include a license
  • v0.1.0 - Initial release

spawning's People

Stargazers

Seth Ryder avatar P.F. Hawkins avatar

Watchers

Dennis Walters avatar James Cloos avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.