web-dev-qa-db-fra.com

Exécuter une commande shell dans Go

Je cherche à exécuter une commande Shell dans Go et à obtenir le résultat obtenu sous forme de chaîne dans mon programme. J'ai vu le Rosetta Code version:

package main
import "fmt"
import "exec"

func main() {
  cmd, err := exec.Run("/bin/ls", []string{"/bin/ls"}, []string{}, "", exec.DevNull, exec.PassThrough, exec.PassThrough)
  if (err != nil) {
    fmt.Println(err)
    return
  }
  cmd.Close()

Mais cela ne capture pas la sortie standard standard ni les erreurs commises de manière programmable - celles-ci sont toujours imprimées sur la sortie standard/stderr normale. J'ai vu qu'utiliser Pipe comme solution de rechange ou d'erreur pourrait aider ailleurs, mais je n'ai pas d'exemple de la façon de le faire Des idées?

31
Chris Bunch

Cette réponse ne représente pas l'état actuel de la bibliothèque standard Go. S'il vous plaît jeter un oeil à la réponse de @ Lourenco pour une méthode à jour!


Votre exemple ne lit pas les données de stdout. Cela fonctionne pour moi.

package main

import (
   "fmt"
   "exec"
   "os"
   "bytes"
   "io"
)

func main() {
    app := "/bin/ls"
    cmd, err := exec.Run(app, []string{app, "-l"}, nil, "", exec.DevNull, exec.Pipe, exec.Pipe)

    if (err != nil) {
       fmt.Fprintln(os.Stderr, err.String())
       return
    }

    var b bytes.Buffer
    io.Copy(&b, cmd.Stdout)
    fmt.Println(b.String())

    cmd.Close()
}
0
jimt

Le paquet "exec" était a légèrement changé . Le code suivant a fonctionné pour moi.

package main

import "os/exec"

func main() {
    app := "echo"
    //app := "buah"

    arg0 := "-e"
    arg1 := "Hello world"
    arg2 := "\n\tfrom"
    arg3 := "golang"

    cmd := exec.Command(app, arg0, arg1, arg2, arg3)
    stdout, err := cmd.Output()

    if err != nil {
        println(err.Error())
        return
    }

    print(string(stdout))
}

J'espère que ça aide!

84
Lourenco

Aucune des réponses fournies ne permet de séparer stdout et stderr alors j'essaie une autre réponse.

Vous obtenez d’abord toutes les informations dont vous avez besoin, si vous consultez la documentation du type exec.Cmd dans le package os/exec. Regardez ici: https://golang.org/pkg/os/exec/#Cmd

En particulier, les membres Stdin et Stdout, Stderr où tout io.Reader peut être utilisé pour alimenter stdin de votre processus nouvellement créé et tout io.Writer utilisé pour consommer stdout et stderr de votre commande.

La fonction Shellout dans le programme suivant lancera votre commande et vous remettra sa sortie et sa sortie d'erreur séparément sous forme de chaînes:

package main

import (
    "bytes"
    "fmt"
    "log"
    "os/exec"
)

const ShellToUse = "bash"

func Shellout(command string) (error, string, string) {
    var stdout bytes.Buffer
    var stderr bytes.Buffer
    cmd := exec.Command(ShellToUse, "-c", command)
    cmd.Stdout = &stdout
    cmd.Stderr = &stderr
    err := cmd.Run()
    return err, stdout.String(), stderr.String()
}

func main() {
    err, out, errout := Shellout("ls -ltr")
    if err != nil {
        log.Printf("error: %v\n", err)
    }
    fmt.Println("--- stdout ---")
    fmt.Println(out)
    fmt.Println("--- stderr ---")
    fmt.Println(errout)
}
4
typetetris
// 封装exec ,有Shell= true 这样的选项

func Cmd(cmd string, Shell bool) []byte {

if Shell {
    out, err := exec.Command("bash", "-c", cmd).Output()
    if err != nil {
        panic("some error found")
    }
    return out
} else {
    out, err := exec.Command(cmd).Output()
    if err != nil {
        panic("some error found")
    }
    return out

}
}

vous pouvez essayer ceci.

2
qing

Voici une fonction simple qui exécutera votre commande et capturera l’erreur, stdout et stderr à inspecter. Vous pouvez facilement voir tout ce qui pourrait mal tourner ou vous être signalé.

// RunCMD is a simple wrapper around terminal commands
func RunCMD(path string, args []string, debug bool) (out string, err error) {

    cmd := exec.Command(path, args...)

    var b []byte
    b, err = cmd.CombinedOutput()
    out = string(b)

    if debug {
        fmt.Println(strings.Join(cmd.Args[:], " "))

        if err != nil {
            fmt.Println("RunCMD ERROR")
            fmt.Println(out)
        }
    }

    return
}

Vous pouvez l'utiliser comme ceci (Conversion d'un fichier multimédia):

args := []string{"-y", "-i", "movie.mp4", "movie_audio.mp3", "INVALID-ARG!"}
output, err := RunCMD("ffmpeg", args, true)

if err != nil {
    fmt.Println("Error:", output)
} else {
    fmt.Println("Result:", output)
}

J'ai utilisé cela avec Go 1.2-1.7

0
Xeoncross