Skip to content

Repository files navigation

cmdio

Go ReferenceGo Report Card

A flexible command execution wrapper with I/O redirection for Go. Execute external commands with full control over stdin, stdout, stderr, and process lifecycle.

Features

  • Synchronous and Asynchronous Execution - Run commands blocking or non-blocking
  • Context Support - Cancel commands using Go contexts (Go 1.23+)
  • I/O Redirection - Full control over stdin, stdout, and stderr
  • Process Management - Signal handling, termination, and process information
  • Thread-Safe - Safe for concurrent use with atomic operations
  • Cross-Platform - Works on Linux and Darwin (macOS)

Requirements

  • Go 1.23 or higher

Installation

go get github.com/streamz/cmdio

Usage

Basic Example

package main
import (
"context""fmt""os""os/user""time""github.com/streamz/cmdio"
)
funcmain() {
// Create options for command executionopts:=func() *cmdio.Options {
usr, _:=user.Current()
return&cmdio.Options{
In: os.Stdin,
Out: os.Stdout,
Err: os.Stderr,
Usr: usr,
}
}
// Synchronous executioncmd:=cmdio.New(opts)
info:=cmd.Run("ls", "-la")
fmt.Printf("Exit code: %d\n", info.Exit)
// Asynchronous executioncmd2:=cmdio.New(opts)
started, complete:=cmd2.Start("sleep", "5")
if<-started {
fmt.Println("Command started successfully")
info:=<-completefmt.Printf("Command finished: %+v\n", info)
}
// Context-based execution with timeoutctx, cancel:=context.WithTimeout(context.Background(), 2*time.Second)
defercancel()
cmd3:=cmdio.New(opts)
info=cmd3.RunContext(ctx, "sleep", "10")
ifinfo.Signaled {
fmt.Println("Command was terminated due to timeout")
}
}

I/O Redirection

package main
import (
"bytes""fmt""os/user""github.com/streamz/cmdio"
)
funcmain() {
// Capture command outputvarstdout, stderr bytes.Bufferopts:=func() *cmdio.Options {
usr, _:=user.Current()
return&cmdio.Options{
In: nil,
Out: &stdout,
Err: &stderr,
Usr: usr,
}
}
cmd:=cmdio.New(opts)
info:=cmd.Run("echo", "Hello, World!")
fmt.Printf("Output: %s", stdout.String())
fmt.Printf("Errors: %s", stderr.String())
fmt.Printf("Exit code: %d\n", info.Exit)
}

Process Termination

package main
import (
"time""os""os/user""github.com/streamz/cmdio"
)
funcmain() {
opts:=func() *cmdio.Options {
usr, _:=user.Current()
return&cmdio.Options{
In: os.Stdin,
Out: os.Stdout,
Err: os.Stderr,
Usr: usr,
}
}
cmd:=cmdio.New(opts)
started, complete:=cmd.Start("sleep", "60")
if<-started {
// Let it run for 2 secondstime.Sleep(2*time.Second)
// Terminate the commanderr:=cmd.Terminate()
iferr!=nil {
panic(err)
}
info:=<-completeifinfo.Signaled {
fmt.Println("Command was successfully terminated")
}
}
}

API Documentation

Full API documentation is available at pkg.go.dev.

Platform-Specific Behavior

Darwin (macOS)

  • Supports process group management
  • Forwards signals to child processes
  • Uses BSD-specific system calls for process enumeration

Linux

  • Supports process death signal (Pdeathsig)
  • Automatic cleanup when parent dies

Testing

Run tests with coverage:

go test -cover ./...

Run benchmarks:

go test -bench=. -benchmem ./...

License

Apache License 2.0 - See LICENSE file for details

About

flexible cmd wrapper and io redirector

Resources

Stars

2 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages