HOWTO · Go
Comment exécuter une commande shell en Go
Apprenez à exécuter des programmes externes depuis Go avec os/exec, capturer la sortie, gérer les erreurs, passer des arguments et définir un répertoire de travail pour une commande. Les fonctionnalités du shell nécessitent d'invoquer explicitement un shell.
Sur cette page
Pour exécuter un programme externe depuis Go, utilisez le paquet os/exec de la bibliothèque standard. Il démarre directement l’exécutable nommé ; il n’exécute pas implicitement un shell. Les fonctionnalités du shell telles que les tubes, la redirection, l’expansion des variables et les caractères génériques ne sont donc pas appliquées. Si une tâche nécessite ces fonctionnalités, invoquez explicitement un shell et transmettez son script en argument, en prenant soin de ne pas placer de texte non fiable dans ce script.
Exécuter une commande avec os/exec
Créez une commande avec exec.Command, puis appelez une méthode telle que Output pour la démarrer et collecter sa sortie standard. Le premier argument nomme l’exécutable, et les arguments restants sont transmis à ce programme. Ce programme complet se lance lui-même comme un processus enfant avec un argument. L’enfant imprime une ligne fixe, et le parent capture cette sortie standard et l’écrit dans sa propre sortie standard. Le programme imprime la ligne de l’enfant par l’intermédiaire du processus parent.
package main
import (
"fmt"
"os"
"os/exec"
)
func main() {
if len(os.Args) > 1 && os.Args[1] == "child" {
fmt.Println("hello from child")
return
}
cmd := exec.Command(os.Args[0], "child")
output, err := cmd.Output()
if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
fmt.Print(string(output))
}
hello from child
Ici, os.Args[0] identifie l’exécutable actuel, de sorte que l’exemple ne dépend pas de l’installation d’un utilitaire séparé. Dans une application, remplacez-le par l’exécutable dont vous avez besoin, tel que git ou go, et fournissez les arguments de ce programme séparément.
Capturer la sortie et gérer les erreurs
Vérifiez l’erreur renvoyée par Output ou CombinedOutput avant d’utiliser le résultat. Un échec au démarrage d’un programme, tel qu’un exécutable introuvable, diffère d’un programme qui démarre et se termine avec un statut non nul. Dans ce dernier cas, l’erreur est généralement un *exec.ExitError ; inspectez-la lorsque le statut de sortie compte. Le type Cmd vous permet également de connecter directement les flux : définissez cmd.Stdout ou cmd.Stderr sur un writer lorsque vous voulez que la sortie y soit envoyée plutôt que collectée dans une tranche d’octets.
Utilisez Output lorsque la sortie standard correspond aux données dont votre programme a besoin. Utilisez CombinedOutput lorsque vous avez également besoin de l’erreur standard dans les octets renvoyés ; les deux flux sont combinés, de sorte que leur ordre relatif n’est pas un moyen fiable de reconstruire des flux séparés. Lorsque les diagnostics doivent rester distincts, attribuez des writers séparés à cmd.Stdout et cmd.Stderr. Gérez et signalez les erreurs au point où l’appelant peut décider de réessayer, de revenir ou de continuer ; imprimer une erreur puis traiter la commande comme réussie peut masquer une opération échouée.
Passer des arguments à une commande
Transmettez chaque argument comme sa propre chaîne après le nom de l’exécutable, par exemple exec.Command("grep", "-n", pattern, filename). Go ne joint pas ces valeurs en une commande shell et n’interprète pas les espaces, les guillemets, les tubes ou les caractères de redirection pour vous. Un nom de fichier contenant des espaces reste un argument lorsqu’il est fourni comme une seule chaîne. Cela évite l’analyse du shell, mais ne valide pas l’entrée pour le programme invoqué : un argument peut toujours avoir une signification particulière pour ce programme, alors validez les valeurs selon l’interface propre de la commande.
Pour les flux d’entrée et de sortie, attribuez un io.Reader à cmd.Stdin et des writers à cmd.Stdout ou cmd.Stderr, puis appelez Run. L’exécutable d’exemple ci-dessus utilise Output parce qu’il n’a besoin que de capturer un court résultat. Utilisez Run lorsque vous voulez connecter les flux et n’avez pas besoin de collecter la sortie standard comme valeur de retour. L’exécutable doit être disponible pour le processus, et ses options peuvent différer selon les systèmes d’exploitation.
Exécuter une commande dans un répertoire différent
Définissez cmd.Dir avant de démarrer la commande pour choisir son répertoire de travail. Par exemple, après avoir construit une commande, définissez cmd.Dir = projectDir puis appelez Output, CombinedOutput ou Run. Le répertoire doit exister et être accessible au processus. Un cmd.Dir relatif est résolu par rapport au répertoire de travail actuel du processus Go ; utilisez un chemin absolu lorsque le répertoire de départ de l’appelant peut varier. Ce paramètre modifie le répertoire du processus enfant et ne modifie pas le répertoire de travail propre du processus Go.