sh

package module
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 3, 2021 License: Apache-2.0 Imports: 14 Imported by: 35

README

CI PkgGoDev

go-sh

install: go get gomodules.xyz/go-sh

Pipe Example:

package main

import "gomodules.xyz/go-sh"

func main() {
	sh.Command("echo", "hello\tworld").Command("cut", "-f2").Run()
}

Because I like os/exec, go-sh is very much modelled after it. However, go-sh provides a better experience.

These are some of its features:

  • keep the variable environment (e.g. export)
  • alias support (e.g. alias in shell)
  • remember current dir
  • pipe command
  • shell build-in commands echo & test
  • timeout support

Examples are important:

sh: echo hello
go: sh.Command("echo", "hello").Run()

sh: export BUILD_ID=123
go: s = sh.NewSession().SetEnv("BUILD_ID", "123")

sh: alias ll='ls -l'
go: s = sh.NewSession().Alias('ll', 'ls', '-l')

sh: (cd /; pwd)
go: sh.Command("pwd", sh.Dir("/")).Run()

sh: test -d data || mkdir data
go: if ! sh.Test("dir", "data") { sh.Command("mkdir", "data").Run() }

sh: cat first second | awk '{print $1}'
go: sh.Command("cat", "first", "second").Command("awk", "{print $1}").Run()

sh: count=$(echo "one two three" | wc -w)
go: count, err := sh.Echo("one two three").Command("wc", "-w").Output()

sh(in ubuntu): timeout 1s sleep 3
go: c := sh.Command("sleep", "3"); c.Start(); c.WaitTimeout(time.Second) # default SIGKILL
go: out, err := sh.Command("sleep", "3").SetTimeout(time.Second).Output() # set session timeout and get output)

sh: echo hello | cat
go: out, err := sh.Command("cat").SetInput("hello").Output()

sh: cat # read from stdin
go: out, err := sh.Command("cat").SetStdin(os.Stdin).Output()

sh: ls -l > /tmp/listing.txt # write stdout to file
go: err := sh.Command("ls", "-l").WriteStdout("/tmp/listing.txt")

If you need to keep env and dir, it is better to create a session

session := sh.NewSession()
session.SetEnv("BUILD_ID", "123")
session.SetDir("/")
# then call cmd
session.Command("echo", "hello").Run()
# set ShowCMD to true for easily debug
session.ShowCMD = true

By default, pipeline returns error only if the last command exit with a non-zero status. However, you can also enable pipefail option like bash. In that case, pipeline returns error if any of the commands fail and for multiple failed commands, it returns the error of rightmost failed command.

session := sh.NewSession()
session.PipeFail = true
session.Command("cat", "unknown-file").Command("echo").Run()

By default, pipelines's std-error is set to last command's std-error. However, you can also combine std-errors of all commands into pipeline's std-error using session.PipeStdErrors = true.

for more information, it better to see docs. Go Walker

contribute

If you love this project, starring it will encourage the coder. Pull requests are welcome.

support the author: alipay

thanks

this project is based on http://github.com/codegangsta/inject. thanks for the author.

the reason to use Go shell

Sometimes we need to write shell scripts, but shell scripts are not good at working cross platform, Go, on the other hand, is good at that. Is there a good way to use Go to write shell like scripts? Using go-sh we can do this now.

Documentation

Overview

Package go-sh is intended to make shell call with golang more easily. Some usage is more similar to os/exec, eg: Run(), Output(), Command(name, args...)

But with these similar function, pipe is added in and this package also got shell-session support.

Why I love golang so much, because the usage of golang is simple, but the power is unlimited. I want to make this pakcage got the sample style like golang.

// just like os/exec
sh.Command("echo", "hello").Run()

// support pipe
sh.Command("echo", "hello").Command("wc", "-c").Run()

// create a session to store dir and env
sh.NewSession().SetDir("/").Command("pwd")

// shell buildin command - "test"
sh.Test("dir", "mydir")

// like shell call: (cd /; pwd)
sh.Command("pwd", sh.Dir("/")) same with sh.Command(sh.Dir("/"), "pwd")

// output to json and xml easily
v := map[string] int {}
err = sh.Command("echo", `{"number": 1}`).UnmarshalJSON(&v)

Index

Examples

Constants

This section is empty.

Variables

View Source
var ErrExecTimeout = errors.New("execute timeout")

Functions

func Go

func Go(f func() error) chan error

func Test

func Test(exp string, arg string) bool

expression can be d,dir, f,file, link

Example
if sh.Test("dir", "mydir") {
	fmt.Println("mydir exists")
}
Output:

Types

type Dir

type Dir string

type Session

type Session struct {
	Env     map[string]string
	Stdin   io.Reader
	Stdout  io.Writer
	Stderr  io.Writer
	ShowCMD bool // enable for debug

	// additional pipe options
	PipeFail      bool // returns error of rightmost no-zero command
	PipeStdErrors bool // combine std errors of all pipe commands
	// contains filtered or unexported fields
}

func Command

func Command(name string, a ...interface{}) *Session
Example
out, err := sh.Command("echo", "hello").Output()
fmt.Println(string(out), err)
Output:

func Echo

func Echo(in string) *Session

func InteractiveSession

func InteractiveSession() *Session

func NewSession

func NewSession() *Session

func (*Session) Alias

func (s *Session) Alias(alias, cmd string, args ...string)
Example
s := NewSession()
s.Alias("alias_echo_hello", "echo", "hello")
out, err := s.Command("alias_echo_hello", "world").Output()
if err != nil {
	log.Fatal(err)
}
fmt.Println(string(out))
Output:

hello world

func (*Session) AppendStdout

func (s *Session) AppendStdout(f string) error

func (*Session) Call

func (s *Session) Call(name string, a ...interface{}) error

combine Command and Run

func (*Session) CombinedOutput

func (s *Session) CombinedOutput() (out []byte, err error)

func (*Session) Command

func (s *Session) Command(name string, a ...interface{}) *Session
Example
s := NewSession()
out, err := s.Command("echo", "hello").Output()
if err != nil {
	log.Fatal(err)
}
fmt.Println(string(out))
Output:

hello
Example (Pipe)
s := NewSession()
out, err := s.Command("echo", "hello", "world").Command("awk", "{print $2}").Output()
if err != nil {
	log.Fatal(err)
}
fmt.Println(string(out))
Output:

world

func (*Session) Getwd

func (s *Session) Getwd() string

func (*Session) Kill

func (s *Session) Kill(sig os.Signal)

func (*Session) Output

func (s *Session) Output() (out []byte, err error)

func (*Session) Run

func (s *Session) Run() (err error)

func (*Session) SetDir

func (s *Session) SetDir(dir string) *Session

func (*Session) SetEnv

func (s *Session) SetEnv(key, value string) *Session

func (*Session) SetInput

func (s *Session) SetInput(in string) *Session

func (*Session) SetStdin

func (s *Session) SetStdin(r io.Reader) *Session

func (*Session) SetTimeout

func (s *Session) SetTimeout(d time.Duration) *Session

func (*Session) Start

func (s *Session) Start() (err error)

start command

func (*Session) Test

func (s *Session) Test(expression string, argument string) bool

expression can be dir, file, link

func (*Session) UnmarshalJSON

func (s *Session) UnmarshalJSON(data interface{}) (err error)

unmarshal shell output to decode json

func (*Session) UnmarshalXML

func (s *Session) UnmarshalXML(data interface{}) (err error)

unmarshal command output into xml

func (*Session) Wait

func (s *Session) Wait() error

Should be call after Start() only catch the last command error

func (*Session) WaitTimeout

func (s *Session) WaitTimeout(timeout time.Duration) (err error)

func (*Session) WriteStdout

func (s *Session) WriteStdout(f string) error

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL