# README
execmd
ExecCmd
is a Go package that offers a simplified interface for shell command execution. Built on top of the exec, ExecCmd
enables command invocation in a system shell and combines multiple stdout
and stderr
into a single stdout
with prefixes. It supports both local and remote command execution, with remote commands implemented through the OpenSSH binary.
Key features
- Execute commands in the system shell
- Execute remote shell commands using OpenSSH binary
- Capture outputs for programmatic access
- Real-time
stdout
andstderr
output featuring auto coloring and prefixing - Utilize shell variables, pipes, and redirections
- Compatibility with system SSH configuration (including ssh-agent forwarding)
- Run commands on multiple remote hosts (ideal for cluster operations) with parallel or serial execution options
- Minimum number of third party dependencies
Installation
go get "github.com/mikhae1/execmd"
Then import exec-cmd
in your application:
import "github.com/mikhae1/execmd"
Examples
Local command execution
package main
import "github.com/mikhae1/execmd"
func main() {
// run local command in a shell
execmd.NewCmd().Run("ps aux | grep go")
}
Remote command execution
package main
import "github.com/mikhae1/execmd"
func main() {
// run command on a remote host using ssh
remote := execmd.NewSSHCmd("192.168.1.194")
res, err := remote.Run(`VAR="$(hostname)"; echo "hello $VAR"`)
if err == nil {
fmt.Printf("captured output: %s", res.Stdout)
}
}
Results:
$ /usr/bin/ssh 192.168.1.194 'VAR="$(hostname)"; echo "hello $VAR"'
192.168.1.194 hello host-01.local
captured output: hello host-01.local
Remote cluster command execution
cluster := execmd.NewClusterSSHCmd([]string{"host-01", "host-02", "host-03"})
// execute in parallel order
res, err := cluster.Run(`VAR=std; echo "Hello $VAR out"; echo Hello $VAR err >&2`)
// execute in serial order
res, err = cluster.RunOneByOne(`VAR=std; echo "Hello $VAR out"`)
Parallel execution results:
$ /usr/bin/ssh host-01 'VAR=std; echo "Hello $VAR out"; echo "Hello $VAR err" >&2'
$ /usr/bin/ssh host-02 'VAR=std; echo "Hello $VAR out"; echo "Hello $VAR err" >&2'
$ /usr/bin/ssh host-03 'VAR=std; echo "Hello $VAR out"; echo "Hello $VAR err" >&2'
host-01 Hello std out
host-01@err Hello std err
host-03@err Hello std err
host-03 Hello std out
host-02 Hello std out
host-02@err Hello std err
Serial execution results:
$ /usr/bin/ssh host-01 'VAR=std; echo "Hello $VAR out"; echo Hello $VAR err >&2'
host-01 Hello std out
host-01@err Hello std err
$ /usr/bin/ssh host-02 'VAR=std; echo "Hello $VAR out"; echo Hello $VAR err >&2'
host-02@err Hello std err
host-02 Hello std out
$ /usr/bin/ssh host-03 'VAR=std; echo "Hello $VAR out"; echo Hello $VAR err >&2'
host-03@err Hello std err
host-03 Hello std out
Testing
You should enable SSH
server locally and add your personal ssh key to known_hosts
to avoid password prompting:
ssh-copy-id 127.0.0.1
ssh-copy-id localhost
Run tests:
go test
License
The MIT License (MIT) - see LICENSE for details.
# Functions
NewClusterSSHCmd initializes ClusterSSHCmd with defaults.
NewCmd initializes a Cmd with default settings.
NewSSHCmd initializes SSHCmd with defaults and sets the target host.
# Structs
ClusterCmd wraps SSHCmd and preserves the host name, and saves errors from .Start() for the .Wait() method.
ClusterRes contains the results of the command execution.
ClusterSSHCmd is a wrapper on SSHCmd that allows executing commands on multiple hosts in parallel or sequentially.
Cmd is a wrapper struct around exec.Cmd that provides additional functionality such as recording and muting stdout and stderr, and customizing output prefixes.
CmdRes represents the result of a command, including the stdout and stderr buffers.
SSHCmd is a wrapper on Cmd to invoke ssh commands via OpenSSH binary.