func ExecShellf(command string, args ...interface{}) (string, error) {
	cmd := fmt.Sprintf(command, args...)
	return ExecShellTimeout(cmd, 0, nil)
}
ExecShellf execute a shell command (like bash -c 'your command') but with format replacements
package main
import (
	"bufio"
	"bytes"
	"crypto/sha512"
	"fmt"
	"strings"
	"text/template"
	"time"
	"github.com/go-cmd/cmd"
	"github.com/sirupsen/logrus"
)
type ShellContext struct {
	CmdRef *cmd.Cmd
}
func ExecShellTimeout(command string, timeout time.Duration, ctx *ShellContext) (string, error) {
	logrus.Debugf("shell command: %s", command)
	acmd := cmd.NewCmd("sh", "-c", command)
	statusChan := acmd.Start()  
	running := true
	if ctx != nil {
		ctx.CmdRef = acmd
	}
	if timeout > 0 {
		logrus.Debugf("Enforcing timeout %s", timeout)
		go func() {
			startTime := time.Now()
			for running {
				if time.Since(startTime) >= timeout {
					logrus.Warnf("Stopping command execution because it is taking too long (%d seconds)", time.Since(startTime))
					acmd.Stop()
				}
				time.Sleep(1 * time.Second)
			}
		}()
	}
	<-statusChan
	running = false
	out := GetCmdOutput(acmd)
	status := acmd.Status()
	logrus.Debugf("shell output (%d): %s", status.Exit, out)
	if status.Exit != 0 {
		return out, fmt.Errorf("Failed to run command: '%s'; exit=%d; out=%s", command, status.Exit, out)
	} else {
		return out, nil
	}
}
func ExecShell(command string) (string, error) {
	return ExecShellTimeout(command, 0, nil)
}