Спящий процесс, пока не завершится в Go - PullRequest
0 голосов
/ 22 сентября 2018

Я пытаюсь автоматизировать процесс в Go.Я смог реализовать потоки и сделать процесс соответствующим образом, однако выходные данные смешаны и сопоставлены.

Мне было интересно, есть ли способ показать выходные данные в том виде, как они создаются программой и в соответствии с программой?процесс.Поэтому, если задача A завершается до задачи B, мы показываем вывод A перед B или наоборот.

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 голосов
/ 22 сентября 2018

В своем процессе вы передаете дескриптор файла 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))
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...