mirror of
https://git.mills.io/saltyim/saltyim.git
synced 2024-07-01 03:01:09 +00:00
969a263d06
Co-authored-by: James Mills <prologic@shortcircuit.net.au> Co-authored-by: James Mills <james@mills.io> Co-authored-by: mlctrez <mlctrez@gmail.com> Reviewed-on: https://git.mills.io/saltyim/saltyim/pulls/77 Co-authored-by: mlctrez <mlctrez@noreply@mills.io> Co-committed-by: mlctrez <mlctrez@noreply@mills.io>
49 lines
1.1 KiB
Go
49 lines
1.1 KiB
Go
package exec
|
|
|
|
import (
|
|
"context"
|
|
"io"
|
|
"os/exec"
|
|
"syscall"
|
|
"time"
|
|
)
|
|
|
|
const (
|
|
DefaultRunCmdTimeout = time.Second * 3
|
|
)
|
|
|
|
// RunCmd executes the given command and arguments and stdin and ensures the
|
|
// command takes no longer than the timeout before the command is terminated.
|
|
func RunCmd(timeout time.Duration, env []string, command string, stdin io.Reader, args ...string) (string, error) {
|
|
var (
|
|
ctx context.Context
|
|
cancel context.CancelFunc
|
|
)
|
|
|
|
if timeout > 0 {
|
|
ctx, cancel = context.WithTimeout(context.Background(), timeout)
|
|
} else {
|
|
ctx, cancel = context.WithCancel(context.Background())
|
|
}
|
|
defer cancel()
|
|
|
|
cmd := exec.CommandContext(ctx, command, args...)
|
|
cmd.Env = append(cmd.Env, env...)
|
|
cmd.Stdin = stdin
|
|
|
|
out, err := cmd.CombinedOutput()
|
|
if err != nil {
|
|
if exitError, ok := err.(*exec.ExitError); ok {
|
|
if ws, ok := exitError.Sys().(syscall.WaitStatus); ok && ws.Signal() == syscall.SIGKILL {
|
|
err = &ErrCommandKilled{Err: err, Signal: ws.Signal()}
|
|
} else {
|
|
err = &ErrCommandFailed{Err: err, Status: exitError.ExitCode()}
|
|
}
|
|
}
|
|
|
|
return string(out), err
|
|
}
|
|
|
|
return string(out), nil
|
|
}
|