Run command with timeout and read stdout one line at a time in go

前端 未结 1 696
一整个雨季
一整个雨季 2021-01-07 12:31

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

相关标签:
1条回答
  • 2021-01-07 13:21

    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

    0 讨论(0)
提交回复
热议问题