睡眠过程,直到在Go中完成

时间:2018-09-21 23:01:28

标签: linux bash go

我正在尝试自动化Go中的流程。我已经能够实现线程并进行相应的处理,但是输出是混合的和匹配的。

我想知道是否有一种方法可以显示程序产生的输出,并根据程序的过程显示输出。因此,如果任务A在任务B之前完成,我们将在B之前显示A的输出,反之亦然。

package main

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

var url string
var wg sync.WaitGroup

func nikto() {
    cmd := exec.Command("nikto", "-h", url)
    cmd.Stdout = os.Stdout
    err := cmd.Run()
    if err != nil {
        log.Fatal(err)
    }
    wg.Done()
}

func whois() {

    cmd := exec.Command("whois", "google.co")
    cmd.Stdout = os.Stdout
    err := cmd.Run()
    if err != nil {
        log.Fatal(err)
    }
    wg.Done()
}
func main() {
    fmt.Printf("Please input URL")
    fmt.Scanln(&url)
    wg.Add(1)
    go nikto()
    wg.Add(1)
    go whois()
    wg.Wait()
}

1 个答案:

答案 0 :(得分:0)

在您的进程中,将os.Stdout文件描述符直接传递给您调用的运行子进程的命令。这意味着子进程的STDOUT管道将直接连接到Go程序的标准输出,并且如果两个子进程同时写入,则很有可能会交错。


解决此问题的最简单方法是,您需要在Go程序中缓冲子进程的STDOUT管道的输出,以便可以拦截输出并控制何时打印。

Cmd包中的os/exec类型提供一个函数调用Output(),它将调用子进程并以字节片形式返回STDOUT的内容。您的代码可以轻松修改以实现此模式并处理结果,例如:

func whois() {
    cmd := exec.Command("whois", "google.co")
    out, err := cmd.Output()
    if err != nil {
        log.Fatal(err)
    }
    fmt.Println(out)
    wg.Done()
}

输出交错

如果您使用fmt包中的函数来打印输出,则有no guarantee不会对对fmt.Println的并发调用进行交织。

为防止交错,您可以选择序列化对STDOUT的访问,或使用可以安全使用的记录器(例如log包)。这是在Go流程中序列化对STDOUT的访问的示例:

package main

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

var url string

func nikto(outChan chan<- []byte) {
    cmd := exec.Command("nikto", "-h", url)
    bs, err := cmd.Output()
    if err != nil {
        log.Fatal(err)
    }
    outChan <- bs
}

func whois(outChan chan<- []byte) {
    cmd := exec.Command("whois", "google.com")
    bs, err := cmd.Output()
    if err != nil {
        log.Fatal(err)
    }
    outChan <- bs
}

func main() {
    outChan := make(chan []byte)

    fmt.Printf("Please input URL")
    fmt.Scanln(&url)
    go nikto(outChan)
    go whois(outChan)

    for i := 0; i < 2; i++ {
        bs := <-outChan
        fmt.Println(string(bs))
    }
}