-
Notifications
You must be signed in to change notification settings - Fork 71
Expand file tree
/
Copy pathshell.go
More file actions
59 lines (52 loc) · 1.6 KB
/
shell.go
File metadata and controls
59 lines (52 loc) · 1.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
package scheduler
import (
"context"
"encoding/json"
"errors"
"os/exec"
"strings"
"github.com/cybertec-postgresql/pg_timetable/internal/pgengine"
)
type commander interface {
CombinedOutput(context.Context, string, ...string) ([]byte, error)
}
type realCommander struct{}
// CombinedOutput executes program command and returns combined stdout and stderr
func (c realCommander) CombinedOutput(ctx context.Context, command string, args ...string) ([]byte, error) {
cmd := exec.CommandContext(ctx, command, args...)
cmd.Stdin = nil
return cmd.CombinedOutput()
}
// Cmd executes a command
var Cmd commander = realCommander{}
// ExecuteProgramCommand executes program command and returns status code, output and error if any
func (sch *Scheduler) ExecuteProgramCommand(ctx context.Context, task *pgengine.ChainTask, paramValues []string) error {
var err error
var exitCode int
command := strings.TrimSpace(task.Command)
if command == "" {
return errors.New("program command cannot be empty")
}
if len(paramValues) == 0 { //mimic empty param
paramValues = []string{""}
}
for _, val := range paramValues {
exitCode = 0
params := []string{}
if val > "" {
if err := json.Unmarshal([]byte(val), ¶ms); err != nil {
return err
}
}
out, e := Cmd.CombinedOutput(ctx, command, params...) // #nosec
if e != nil {
exitCode = -1
err = errors.Join(err, e) // accumulate errors for all param sets
if exitError, ok := err.(*exec.ExitError); ok {
exitCode = exitError.ExitCode()
}
}
sch.pgengine.LogTaskExecution(context.Background(), task, exitCode, string(out), val)
}
return err
}