package process import ( "bytes" "context" "fmt" "os/exec" "strings" "github.com/databricks/cli/libs/env" "github.com/databricks/cli/libs/log" ) type ProcessError struct { Command string Err error Stdout string Stderr string } func (perr *ProcessError) Unwrap() error { return perr.Err } func (perr *ProcessError) Error() string { return fmt.Sprintf("%s: %s", perr.Command, perr.Err) } func Background(ctx context.Context, args []string, opts ...execOption) (string, error) { commandStr := strings.Join(args, " ") log.Debugf(ctx, "running: %s", commandStr) cmd := exec.CommandContext(ctx, args[0], args[1:]...) stdout := bytes.Buffer{} stderr := bytes.Buffer{} // For background processes, there's no standard input cmd.Stdin = nil cmd.Stdout = &stdout cmd.Stderr = &stderr // we pull the env through lib/env such that we can run // parallel tests with anything using libs/process. for k, v := range env.All(ctx) { cmd.Env = append(cmd.Env, fmt.Sprintf("%s=%s", k, v)) } for _, o := range opts { err := o(ctx, cmd) if err != nil { return "", err } } if err := runCmd(ctx, cmd); err != nil { return stdout.String(), &ProcessError{ Err: err, Command: commandStr, Stdout: stdout.String(), Stderr: stderr.String(), } } return stdout.String(), nil }