package utils import ( "bufio" "context" "os/exec" "github.com/go-pay/errgroup" "github.com/pkg/errors" log "github.com/sirupsen/logrus" ) // ExecCommand executes a command and streams its output in real-time func ExecCommand(name string, args ...string) error { log.Infof("Executing command: %s %v", name, args) cmd := exec.Command(name, args...) stdout, err := cmd.StdoutPipe() if err != nil { return errors.Wrap(err, "stdout pipe error") } stderr, err := cmd.StderrPipe() if err != nil { return errors.Wrap(err, "stderr pipe error") } if err := cmd.Start(); err != nil { return errors.Wrap(err, "command start error") } var eg errgroup.Group eg.Go(func(ctx context.Context) error { scanner := bufio.NewScanner(stdout) for scanner.Scan() { log.Info(scanner.Text()) } return nil }) eg.Go(func(ctx context.Context) error { scanner := bufio.NewScanner(stderr) for scanner.Scan() { log.Error(scanner.Text()) } return nil }) if err := cmd.Wait(); err != nil { return errors.Wrap(err, "command wait error") } if err := eg.Wait(); err != nil { return errors.Wrap(err, "command wait error") } return nil } // ExecCommandOutput executes a command and returns its output func ExecCommandOutput(name string, args ...string) ([]byte, error) { log.Infof("Executing command: %s %v", name, args) cmd := exec.Command(name, args...) output, err := cmd.Output() if err != nil { return nil, errors.Wrapf(err, "failed to execute command: %s", name) } return output, nil }