J'écris un programme dans Go qui exécute un programme de type serveur (également Go). Maintenant, je veux avoir la sortie standard du programme enfant dans ma fenêtre de terminal où j'ai démarré le programme parent. Une façon de procéder consiste à utiliser la fonction cmd.Output()
, mais cela n'imprime la sortie standard qu'après la fin du processus. (C'est un problème car ce programme de type serveur fonctionne depuis longtemps et je veux lire la sortie du journal)
La variable out
est de type io.ReadCloser
Et je ne sais pas ce que je dois en faire pour accomplir ma tâche, et je ne trouve rien d'utile sur le Web à ce sujet.
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()
}
Explication du code: décommentez la fonction Println
pour obtenir le code à compiler, je sais que Println(out io.ReadCloser)
n'est pas une fonction significative.
(il produit la sortie &{3 |0 <nil> 0}
) Ces deux lignes sont juste nécessaires pour obtenir le code à compiler.
Maintenant, je veux avoir la sortie standard du programme enfant dans ma fenêtre de terminal où j'ai démarré le programme parent.
Pas besoin de s'embêter avec des pipes ou des goroutines, celui-ci est facile.
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()
}
Je crois que si vous importez io
et os
et remplacez ceci:
//fmt.Println(out)
avec ça:
go io.Copy(os.Stdout, out)
(voir documentation pour io.Copy
et pour os.Stdout
), il fera ce que vous voulez. (Avertissement: non testé.)
Soit dit en passant, vous souhaiterez probablement également capturer l'erreur standard, en utilisant la même approche que pour la sortie standard, mais avec cmd.StderrPipe
et os.Stderr
.
Pour ceux qui n'en ont pas besoin dans une boucle, mais qui souhaitent que la sortie de la commande se répercute dans le terminal sans que cmd.Wait()
bloque d'autres instructions:
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")
}