Maison >développement back-end >Golang >Comment diffuser la sortie partielle d'une commande de longue durée dans Go ?

Comment diffuser la sortie partielle d'une commande de longue durée dans Go ?

Mary-Kate Olsen
Mary-Kate Olsenoriginal
2024-12-24 00:18:15845parcourir

How to Stream Partial Output from a Long-Running Command in Go?

Progression de la sortie de la commande en streaming

Dans les scénarios où une commande de longue durée est exécutée et sa sortie doit être diffusée en continu à la fois vers le processus parent et vers un fichier journal , la méthode cmd.StdoutPipe() peut être utilisée pour capturer le résultat.

cmd := exec.Command("sh", "-c", "some long runnig task")

stdout, _ := cmd.StdoutPipe()
cmd.Start()

scanner := bufio.NewScanner(stdout)
for scanner.Scan() {
    m := scanner.Text()
    fmt.Println(m)
    log.Printf(m)
}

cmd.Wait()

Cependant, cette approche ne fournit que le résultat final comme une seule chaîne, sans diffusion de résultats partiels.

Raisons de la sortie limitée

La fonction bufio.NewScanner() fonctionne sur les lignes, renvoyant une ligne complète lorsqu'un caractère de nouvelle ligne est rencontré. Si la commande en cours d'exécution ne produit pas de caractères de nouvelle ligne, la sortie ne sera pas diffusée immédiatement.

Solutions de contournement possibles

Pour remédier à cette limitation, il existe plusieurs approches à considérer :

  1. Lecture par mots ou caractères :
    En définissant une fonction de partage à l'aide de Scanner.Split(), vous pouvez analyser l'entrée par mots ou caractères, capturant la sortie au fur et à mesure de sa production.

    scanner := bufio.NewScanner(stdout)
    scanner.Split(bufio.ScanRunes)
  2. Lecture manuelle :
    La lecture octet par octet ou rune par rune vous permet de capturer le résultat au fur et à mesure qu'il est généré, sans compter sur une nouvelle ligne. caractères.

    oneByte := make([]byte, 1)
    for {
        _, err := stdout.Read(oneByte)
        if err != nil {
            break
        }
        fmt.Printf("%c", oneByte[0])
    }
    
    oneRune := make([]byte, utf8.UTFMax)
    for {
        count, err := stdout.Read(oneRune)
        if err != nil {
            break
        }
        fmt.Printf("%s", oneRune[:count])
    }

Considérations

Il est crucial de gérer la taille des tampons pour la sortie standard et les flux d'erreurs dans les processus enfants. Par défaut, si ces tampons ne sont pas lus, ils peuvent provoquer le blocage du processus enfant. Par conséquent, il est recommandé de toujours lire les flux stdout et stderr.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn