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
Libérer: 2024-12-24 00:18:15
original
842 Les gens l'ont consulté

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()
Copier après la connexion

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)
    Copier après la connexion
  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])
    }
    Copier après la connexion

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!

source:php.cn
Déclaration de ce site Web
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
Derniers articles par auteur
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal