I\'d like to run a command and print each line from its stdout
(as it becomes available). Further, if the command doesn\'t complete within N seconds, I would li
I think you want to put the body of your default:
case into a goroutine; I suspect it's preventing your case <-time.After(time.Second * 2):
label from being hit.
Also, keep in mind that time.After
does not guarantee that it will be hit exactly after that duration, it only says that any time after that duration it will send the signal on the channel, which could be a while after the designated duration. See the docs on the underlying time.NewTimer
I modified your example: http://play.golang.org/p/TggNQ1d57Y
package main
import (
"bufio"
"fmt"
"log"
"os/exec"
"time"
)
func RunTraceroute(host string) {
errch := make(chan error, 1)
cmd := exec.Command("/usr/bin/traceroute", host)
stdout, err := cmd.StdoutPipe()
if err != nil {
log.Fatal(err)
}
if err := cmd.Start(); err != nil {
log.Fatal(err)
}
go func() {
errch <- cmd.Wait()
}()
go func() {
for _, char := range "|/-\\" {
fmt.Printf("\r%s...%c", "Running traceroute", char)
time.Sleep(100 * time.Millisecond)
}
scanner := bufio.NewScanner(stdout)
fmt.Println("")
for scanner.Scan() {
line := scanner.Text()
log.Println(line)
}
}()
select {
case <-time.After(time.Second * 1):
log.Println("Timeout hit..")
return
case err := <-errch:
if err != nil {
log.Println("traceroute failed:", err)
}
}
}
func main() {
RunTraceroute("8.8.8.8")
}
Which works for me