linux - 休眠过程,直到在 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()
}
解决方案
在您的进程中,您将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))
}
}
推荐阅读
- javascript - Tweenmax Scale with ThreeJS Mesh
- c++ - 设计一个可扩展的多线程应用程序
- angular - Angular 6 Mat-Select does not define user.email through http GET request
- typescript - TypeScript 如何不抱怨一个既不是这个也不是那个的对象
- javascript - 即使在 serviceworker.js 的 addEventListener 中注册,notificationclick 也不会在 chrome 中触发
- javascript - Looking for some approach to put 'moving image' over video (youtube video)?
- reactjs - 为什么 Flow 将我的 React 组件报告为“与字符串不兼容”?
- angular - 无法在 Angular 中获取 API 错误响应
- database - rails:尝试匹配数组中的两个值,得到不支持的参数类型:哈希错误
- reactjs - 如何调试无法在 react-admin 应用程序中获取