I use the following code which works, The problem is that the output is printed just as the process finished to execute, I want to print to the screen the output live and not provide all the output when the process finishes, how can I achieve this?
cmdParams := [][]string{
{filepath.Join(dir,path), "npm", "install"},
{filepath.Join(pdir,n.path), "gulp"},
}
for _, cp := range cmdParams {
log.Printf("Starting %s in folder %s...", cp[1:], cp[0])
cmd := exec.Command(cp[1], cp[2:]...)
cmd.Dir = cp[0]
// Wait to finish, get output:
out, err := cmd.Output()
if err != nil {
log.Printf("Error running %s: %v
", cp[1:], err)
return
}
log.Println("Finished %s, output: %s", cp[1:], out)
}
update when trying the proposed solution I got the output like
2018/02/18 11:11:57 Starting [npm install] in folder ...
2018/02/18 11:12:14 adde
2018/02/18 11:12:14 d 56
2018/02/18 11:12:14 3 pa
2018/02/18 11:12:14 ckag
2018/02/18 11:12:14 es i
2018/02/18 11:12:14 n 15
2018/02/18 11:12:14 .477
2018/02/18 11:12:14 s
2018/02/18 11:12:14 Finished %s [npm install]
Using the solution presented in this answer: Streaming commands output progress
cmdParams := [][]string{
{filepath.Join(dir, path), "npm", "install"},
{filepath.Join(pdir, n.path), "gulp"},
}
for _, cp := range cmdParams {
log.Printf("Starting %s in folder %s...", cp[1:], cp[0])
cmd := exec.Command(cp[1], cp[2:]...)
cmd.Dir = cp[0]
stdout, err := cmd.StdoutPipe()
if err != nil {
log.Printf("%s cmd.StdoutPipe() error: %v
", cp[1:], err)
return
}
// Start command:
if err = cmd.Start(); err != nil {
log.Printf("%s start error: %v
", cp[1:], err)
return
}
// Stream command output:
scanner := bufio.NewScanner(stdout)
scanner.Split(bufio.ScanRunes)
for scanner.Scan() {
fmt.Print(scanner.Text())
}
if scanner.Err() != nil {
log.Printf("Reading %s stdout error: %v
", cp[1:], err)
return
}
// Get execution success or failure:
if err = cmd.Wait(); err != nil {
log.Printf("Error running %s: %v
", cp[1:], err)
return
}
log.Printf("Finished %s", cp[1:])
}
Some explanation:
This line:
scanner := bufio.NewScanner(stdout)
Creates a bufio.Scanner
that will read from the pipe that supplies the output written by the process.
This line:
scanner.Split(bufio.ScanRunes)
Instructs the scanner to read the input by rune
s instead of the default by-lines.
Note that the above example only streams the standard output of the process. If you also need its standard error stream, you could also read from Command.StderrPipe()
.
Also note that this won't work with some commands that don't write everything to their standard output or error. For details, see How to get the realtime output for a shell command in golang?