Skip to content

Instantly share code, notes, and snippets.

@hivefans
Last active May 12, 2024 10:36
Show Gist options
  • Save hivefans/ffeaf3964924c943dd7ed83b406bbdea to your computer and use it in GitHub Desktop.
Save hivefans/ffeaf3964924c943dd7ed83b406bbdea to your computer and use it in GitHub Desktop.
get the realtime output for a shell command in golang|-|{"files":{"shell_output.go":{"env":"plain"}},"tag":"bigdata"}
package main
import (
"bufio"
"fmt"
"io"
"os"
"os/exec"
"strings"
)
func main() {
cmdName := "ping 127.0.0.1"
cmdArgs := strings.Fields(cmdName)
cmd := exec.Command(cmdArgs[0], cmdArgs[1:len(cmdArgs)]...)
stdout, _ := cmd.StdoutPipe()
cmd.Start()
oneByte := make([]byte, 100)
num := 1
for {
_, err := stdout.Read(oneByte)
if err != nil {
fmt.Printf(err.Error())
break
}
r := bufio.NewReader(stdout)
line, _, _ := r.ReadLine()
fmt.Println(string(line))
num = num + 1
if num > 3 {
os.Exit(0)
}
}
cmd.Wait()
}
@smc181002
Copy link

For people coming from google - I revised a bit.

package main

import (
  "bufio"
  "os"
  "os/exec"
  "fmt"
  "log"
)

func main() {
  cmd := exec.Command("ping", "127.0.0.1")
  stdout, err := cmd.StdoutPipe()
  if err != nil {
    log.Fatal(err)
  }
  cmd.Start()

  buf := bufio.NewReader(stdout) // Notice that this is not in a loop
  num := 1
  for {
    line, _, _ := buf.ReadLine()
    if num > 3 {
      os.Exit(0)
    }
    num += 1
    fmt.Println(string(line))
  }
}

when I ran this, the ping command is stopping after an interval of time.
I use windows and ping in windows pings 4 times as default similar to ping -c4 127.0.0.1
but is there a way where we can get the return value of the command and stop the for loop?

@MiranDaniel
Copy link

Still up to date, March 21 2022

@Masternetworks
Copy link

Nice !

@cwbriscoe
Copy link

Here is another example that I made based on the code posted above:

func RunCmd(ctx context.Context, cmdstr string) error {
	args := strings.Fields(cmdstr)
	cmd := exec.CommandContext(ctx, args[0], args[1:]...)

	stdout, err := cmd.StdoutPipe()
	if err != nil {
		return err
	}

	var wg sync.WaitGroup
	wg.Add(1)

	scanner := bufio.NewScanner(stdout)
	go func() {
		for scanner.Scan() {
			log.Printf("out: %s", scanner.Text())
		}
		wg.Done()
	}()

	if err = cmd.Start(); err != nil {
		return err
	}

	wg.Wait()

	return cmd.Wait()
}

@joseluis10101
Copy link

Maybe you should use multiwritter:

cmd.Stdout = io.MultiWriter(os.Stdout, &stdout) cmd.Stderr = io.MultiWriter(os.Stderr, &stderr)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment