orion/openwrt/executor.go

68 lines
1.6 KiB
Go

package openwrt
import (
"bytes"
"fmt"
"log"
"os/exec"
"syscall"
)
// Executor interface to describe command runners signature
type Executor interface {
Run(command string, params ...string) *CommandResult
}
// CommandResult contain all information about a command execution, stdout, stderr
type CommandResult struct {
Stdout string
Stderr string
ReturnCode int
}
type localExecutor struct{}
func (e *localExecutor) Run(command string, params ...string) *CommandResult {
var out bytes.Buffer
var stderr bytes.Buffer
var exitCode int
defaultFailedCode := 255
exe := exec.Command(command, params...)
exe.Stdout = &out
exe.Stderr = &stderr
err := exe.Run()
if err != nil {
if exitError, ok := err.(*exec.ExitError); ok {
ws := exitError.Sys().(syscall.WaitStatus)
exitCode = ws.ExitStatus()
} else {
// This will happen (in OSX) if `name` is not available in $PATH,
// in this situation, exit code could not be get, and stderr will be
// empty string very likely, so we use the default fail code, and format err
// to string and set to stderr
log.Printf("Could not get exit code for failed program: %v, %v", command, params)
exitCode = defaultFailedCode
}
fmt.Println(fmt.Sprint(err) + ": " + stderr.String())
log.Fatal(err)
}
if err != nil {
// try to get the exit code
} else {
// success, exitCode should be 0 if go is ok
ws := exe.ProcessState.Sys().(syscall.WaitStatus)
exitCode = ws.ExitStatus()
}
return &CommandResult{
Stdout: out.String(),
Stderr: stderr.String(),
ReturnCode: exitCode,
}
}