1 回答
TA贡献1942条经验 获得超3个赞
在您的进程中,您将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包中的函数来打印输出,则不能保证并发调用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))
}
}
- 1 回答
- 0 关注
- 248 浏览
添加回答
举报