为执行的进程创建等待/忙碌指示符

时间:2018-05-22 11:54:31

标签: go command-line command-line-interface

我执行子程序的程序,如

cmd := exec.Command("npm", "install")
log.Printf("Running command and waiting for it to finish...")
err := cmd.Run()
log.Printf("Command finished with error: %v", err)

当这个命令运行时,下载并安装npm软件包需要10到40秒的时间,用户不知道发生什么事情,直到他看到stdout(10-40秒取决于网络),有什么东西我可以使用哪些东西打印到cli,以便更清楚地发生某些事情,一些繁忙的指示符(任何类型),直到stdout被打印到cli?

2 个答案:

答案 0 :(得分:4)

您可以使用另一个goroutine定期打印某些内容(如点),就像每秒钟一样。当命令完成时,指示goroutine终止。

这样的事情:

func indicator(shutdownCh <-chan struct{}) {
    ticker := time.NewTicker(time.Second)
    defer ticker.Stop()
    for {
        select {
        case <-ticker.C:
            fmt.Print(".")
        case <-shutdownCh:
            return
        }
    }
}

func main() {
    cmd := exec.Command("npm", "install")
    log.Printf("Running command and waiting for it to finish...")

    // Start indicator:
    shutdownCh := make(chan struct{})
    go indicator(shutdownCh)

    err := cmd.Run()

    close(shutdownCh) // Signal indicator() to terminate

    fmt.Println()
    log.Printf("Command finished with error: %v", err)
}

如果你想在每5个点后开始一个新行,这就是它的完成方式:

func indicator(shutdownCh <-chan struct{}) {
    ticker := time.NewTicker(time.Second)
    defer ticker.Stop()
    for i := 0; ; {
        select {
        case <-ticker.C:
            fmt.Print(".")
            if i++; i%5 == 0 {
                fmt.Println()
            }
        case <-shutdownCh:
            return
        }
    }
}

答案 1 :(得分:1)

另一种方法是转变icza的答案。由于npm命令是一个长时间运行的执行,因此最好使用goroutine而不是自动收报机(或两者都作为goroutine),但这是一个偏好的问题。

像这样:

func npmInstall(done chan struct{}) {
    cmd := exec.Command("npm", "install")
    log.Printf("Running command and waiting for it to finish...")

    err := cmd.Run()
    if err != nil {
        log.Printf("\nCommand finished with error: %v", err)
    }
    close(done)
}

func main() {
    done := make(chan struct{})
    go npmInstall(done)

    ticker := time.NewTicker(3 * time.Second)
    defer ticker.Stop()
    for {
        select {
        case <-ticker.C:
            fmt.Print(".")
        case <-done:
            fmt.Println()
            return
        }
    }
}