package util import ( "bufio" "bytes" "context" "fmt" "os/exec" "strings" "github.com/beclab/Olares/cli/pkg/core/logger" "github.com/pkg/errors" ) func ExecWithContext(ctx context.Context, name string, printOutput bool, printLine bool) (stdout string, code int, err error) { exitCode := 0 logger.Debugf("[exec] try to exec CMD: %s", name) cmd := exec.CommandContext(ctx, "/bin/bash", "-c", name) out, err := cmd.StdoutPipe() if err != nil { return "", exitCode, err } // logger.Infof("exec cmd: %s", cmd.String()) cmd.Stderr = cmd.Stdout if err := cmd.Start(); err != nil { exitCode = -1 if exitErr, ok := err.(*exec.ExitError); ok { exitCode = exitErr.ExitCode() } return "", exitCode, err } var outputBuffer bytes.Buffer r := bufio.NewReader(out) for { line, err := r.ReadString('\n') if err != nil { if err.Error() != "EOF" { logger.Errorf("[exec] read error: %s", err) } if printLine && line != "" { fmt.Println(strings.TrimSuffix(line, "\n")) } outputBuffer.WriteString(line) break } if printLine && line != "" { fmt.Println(strings.TrimSuffix(line, "\n")) } outputBuffer.WriteString(line) } err = cmd.Wait() if err != nil { exitCode = -1 if exitErr, ok := err.(*exec.ExitError); ok { exitCode = exitErr.ExitCode() } } res := outputBuffer.String() res = strings.TrimSpace(res) if printOutput { fmt.Printf("[exec] CMD: %s, OUTPUT: \n%s\n", cmd.String(), res) } logger.Debugf("[exec] CMD: %s, OUTPUT: %s", cmd.String(), res) return res, exitCode, errors.Wrapf(err, "Failed to exec command: %s \n%s", cmd, res) } func Exec(ctx context.Context, name string, printOutput bool, printLine bool) (stdout string, code int, err error) { exitCode := 0 logger.Debugf("[exec] try to exec CMD: %s", name) cmd := exec.CommandContext(ctx, "/bin/bash", "-c", name) out, err := cmd.StdoutPipe() if err != nil { return "", exitCode, err } cmd.Stderr = cmd.Stdout if err := cmd.Start(); err != nil { exitCode = -1 if exitErr, ok := err.(*exec.ExitError); ok { exitCode = exitErr.ExitCode() } return "", exitCode, err } var outputBuffer bytes.Buffer r := bufio.NewReader(out) for { line, err := r.ReadString('\n') if err != nil { if err.Error() != "EOF" { logger.Errorf("[exec] read error: %s", err) } if printLine && line != "" { fmt.Println(strings.TrimSuffix(line, "\n")) } outputBuffer.WriteString(line) break } if printLine && line != "" { fmt.Println(strings.TrimSuffix(line, "\n")) } outputBuffer.WriteString(line) } err = cmd.Wait() if err != nil { exitCode = -1 if exitErr, ok := err.(*exec.ExitError); ok { exitCode = exitErr.ExitCode() } } res := outputBuffer.String() res = strings.TrimSpace(res) if printOutput { fmt.Printf("[exec] CMD: %s, OUTPUT: \n%s\n", cmd.String(), res) } logger.Debugf("[exec] CMD: %s, OUTPUT: %s", cmd.String(), res) return res, exitCode, errors.Wrapf(err, "Failed to exec command: %s \n%s", cmd, res) }