睡眠过程直到在 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()

}


子衿沉夜
浏览 156回答 1
1回答

手掌心

在您的进程中,您将os.Stdout文件描述符直接传递给您调用以运行子进程的命令。这意味着子进程的 STDOUT 管道将直接连接到您的 Go 程序的标准输出,并且如果两个子进程同时写入,则可能会交错。解决这个问题的最简单方法需要您在 Go 程序中缓冲来自子进程的 STDOUT 管道的输出,这样您就可以拦截输出并在打印时进行控制。Cmd包中的类型提供os/exec了一个函数调用Output(),它将调用子进程并以字节片的形式返回 STDOUT 的内容。您的代码可以轻松调整以实现此模式并处理结果,例如:func whois() {&nbsp; &nbsp; cmd := exec.Command("whois", "google.co")&nbsp; &nbsp; out, err := cmd.Output()&nbsp; &nbsp; if err != nil {&nbsp; &nbsp; &nbsp; &nbsp; log.Fatal(err)&nbsp; &nbsp; }&nbsp; &nbsp; fmt.Println(out)&nbsp; &nbsp; wg.Done()}交织输出如果您使用fmt包中的函数来打印输出,则不能保证并发调用fmt.Println不会交错。为防止交错,您可以选择序列化对 STDOUT 的访问,或使用可安全并发使用的记录器(例如包log)。下面是一个在 Go 进程中序列化访问 STDOUT 的例子:package mainimport (&nbsp; &nbsp; "fmt"&nbsp; &nbsp; "log"&nbsp; &nbsp; "os/exec"&nbsp; &nbsp; "sync")var url stringfunc nikto(outChan chan<- []byte) {&nbsp; &nbsp; cmd := exec.Command("nikto", "-h", url)&nbsp; &nbsp; bs, err := cmd.Output()&nbsp; &nbsp; if err != nil {&nbsp; &nbsp; &nbsp; &nbsp; log.Fatal(err)&nbsp; &nbsp; }&nbsp; &nbsp; outChan <- bs}func whois(outChan chan<- []byte) {&nbsp; &nbsp; cmd := exec.Command("whois", "google.com")&nbsp; &nbsp; bs, err := cmd.Output()&nbsp; &nbsp; if err != nil {&nbsp; &nbsp; &nbsp; &nbsp; log.Fatal(err)&nbsp; &nbsp; }&nbsp; &nbsp; outChan <- bs}func main() {&nbsp; &nbsp; outChan := make(chan []byte)&nbsp; &nbsp; fmt.Printf("Please input URL")&nbsp; &nbsp; fmt.Scanln(&url)&nbsp; &nbsp; go nikto(outChan)&nbsp; &nbsp; go whois(outChan)&nbsp; &nbsp; for i := 0; i < 2; i++ {&nbsp; &nbsp; &nbsp; &nbsp; bs := <-outChan&nbsp; &nbsp; &nbsp; &nbsp; fmt.Println(string(bs))&nbsp; &nbsp; }}
打开App,查看更多内容
随时随地看视频慕课网APP