web-dev-qa-db-fra.com

Comment déboguer l'erreur "exit status 1" lors de l'exécution de exec.Command dans Golang

Lorsque j'exécute le code ci-dessous:

cmd := exec.Command("find", "/", "-maxdepth", "1", "-exec", "wc", "-c", "{}", "\\")
var out bytes.Buffer
cmd.Stdout = &out
err := cmd.Run()
if err != nil {
    fmt.Println(err)
    return
}
fmt.Println("Result: " + out.String())

Je reçois cette erreur:

état de sortie 1

Cependant, cela n'est pas utile pour déboguer la cause exacte de l'erreur.

Comment obtenir des informations plus détaillées?

35
laurent

La solution consiste à utiliser la propriété Stderr de l'objet Command. Cela peut être fait comme ceci:

cmd := exec.Command("find", "/", "-maxdepth", "1", "-exec", "wc", "-c", "{}", "\\")
var out bytes.Buffer
var stderr bytes.Buffer
cmd.Stdout = &out
cmd.Stderr = &stderr
err := cmd.Run()
if err != nil {
    fmt.Println(fmt.Sprint(err) + ": " + stderr.String())
    return
}
fmt.Println("Result: " + out.String())

L'exécution du code ci-dessus rendrait clair le problème:

état de sortie 1: trouver: -exec: pas de terminaison ";" ou "+"

Modifier:

Dans le code ci-dessus, nous prévoyons qu'en cas d'erreur, les messages seront imprimés sur stderr et la commande renverra un code d'erreur non nul. C'est plus ou moins standard.

Cependant, comme mentionné ci-dessous par @snorberhuis, certaines commandes affichent les erreurs sur stdout. D'autres commandes peuvent imprimer sur stderr mais retourner un code d'erreur de 0 (auquel cas err sera nil). Et avoir des messages dans stderr ne signifie pas nécessairement qu'il y a une erreur (les outils ffmpeg le font souvent).

Donc, fondamentalement, vous devrez peut-être modifier le code ci-dessus pour répondre aux commandes que vous attendez.

77
laurent

Comme Laurent l'a mentionné, vous pouvez remplacer le descripteur de fichier Stderr pour capturer la sortie stderr pour un meilleur message d'erreur. Personnellement, je préfère utiliser la méthode CombinedOutput pour une commande si vous faites quelque chose de relativement simple:

cmd := exec.Command("find", "/", "-maxdepth", "1", "-exec", "wc", "-c", "{}", "\\")
output, err := cmd.CombinedOutput()
if err != nil {
    fmt.Println(fmt.Sprint(err) + ": " + string(output))
    return
}
fmt.Println(string(output))

Voici un lien play.golang.org pour l'exemple ci-dessus: http://play.golang.org/p/z8k9zO755P

28
noj