Przekierowanie rury stdout procesu potomnego w Go

Piszę program w Go, który wykonuje program podobny do serwera (również Go). Teraz chcę mieć stdout programu potomnego w moim oknie terminala, w którym uruchomiłem program rodzica. Jednym ze sposobów na to jest funkcja cmd.Output(), ale wypisuje stdout dopiero po zakończeniu procesu. (To jest problem, ponieważ ten serwer podobny program działa przez długi czas i chcę przeczytać wyjście dziennika)

Zmienna out jest z type io.ReadCloser i nie wiem co z nią zrobić aby wykonaj moje zadanie i nie mogę znaleźć w sieci nic pomocnego na ten temat.

func main() {
    cmd := exec.Command("/path/to/my/child/program")
    out, err := cmd.StdoutPipe()
    if err != nil {
        fmt.Println(err)
    }
    err = cmd.Start()
    if err != nil {
        fmt.Println(err)
    }
    //fmt.Println(out)
    cmd.Wait()
} 

Wyjaśnienie kodu: odkomentuj funkcję Println Aby uzyskać kod do kompilacji, wiem, że Println(out io.ReadCloser) nie jest funkcją znaczącą.
(generuje wyjście &{3 |0 <nil> 0}) te dwie linie są po prostu wymagane, aby uzyskać kod do kompilacji.

Author: mbert, 2012-01-16

3 answers

Teraz chcę mieć stdout programu potomnego w moim terminalu okno, w którym uruchomiłem program rodzica.

Nie trzeba zadzierać z rurami lub goroutines, ten jest łatwy.

func main() {
    // Replace `ls` (and its arguments) with something more interesting
    cmd := exec.Command("ls", "-l")
    cmd.Stdout = os.Stdout
    cmd.Stderr = os.Stderr
    cmd.Run()
}
 180
Author: cmccabe,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-02-14 23:06:24

Uważam, że jeśli zaimportujesz io i os i zastąpisz to:

//fmt.Println(out)

Z tym:

go io.Copy(os.Stdout, out)

(patrz dokumentacja dla io.Copy i dla os.Stdout), zrobi to, co chcesz. (Zastrzeżenie: nie testowane.)

Przy okazji, prawdopodobnie będziesz chciał również przechwycić standard-error, używając tego samego podejścia, co dla standard-output, ale z cmd.StderrPipe i os.Stderr.

 17
Author: ruakh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-01-16 02:22:19

Dla tych, którzy nie potrzebują tego w pętli, ale chcieliby, aby wyjście polecenia odbijało się echem w terminalu bez blokowania innych instrukcji cmd.Wait():

package main

import (
    "fmt"
    "io"
    "log"
    "os"
    "os/exec"
)

func checkError(err error) {
    if err != nil {
        log.Fatalf("Error: %s", err)
    }
}

func main() {
    // Replace `ls` (and its arguments) with something more interesting
    cmd := exec.Command("ls", "-l")

    // Create stdout, stderr streams of type io.Reader
    stdout, err := cmd.StdoutPipe()
    checkError(err)
    stderr, err := cmd.StderrPipe()
    checkError(err)

    // Start command
    err = cmd.Start()
    checkError(err)

    // Don't let main() exit before our command has finished running
    defer cmd.Wait()  // Doesn't block

    // Non-blockingly echo command output to terminal
    go io.Copy(os.Stdout, stdout)
    go io.Copy(os.Stderr, stderr)

    // I love Go's trivial concurrency :-D
    fmt.Printf("Do other stuff here! No need to wait.\n\n")
}
 11
Author: elimisteve,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-08-03 11:50:04