В своем процессе вы передаете дескриптор файла os.Stdout
непосредственно командам, которые вы вызываете для запуска ваших дочерних процессов.Это означает, что канал STDOUT дочерних процессов будет напрямую подключен к стандартному выводу вашей программы Go и, вероятно, будет чередоваться, если оба дочерних процесса пишут одновременно.
Самый простой способ исправить это требует от васбуферизируйте вывод из канала STDOUT дочернего процесса в вашей программе Go, чтобы вы могли перехватывать вывод и управление при его печати.
Тип 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
).Вот пример сериализации доступа к STDOUT в процессе Go:
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))
}
}