Exec a shell command in Go

前端 未结 7 1609
甜味超标
甜味超标 2020-12-04 10:01

I\'m looking to execute a shell command in Go and get the resulting output as a string in my program. I saw the Rosetta Code version:

package main
import \"f         


        
相关标签:
7条回答
  • 2020-12-04 10:37
    // 封装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
    
    }
    }
    

    you may try this .

    0 讨论(0)
  • 2020-12-04 10:37

    I did not get the Rosetta example to work in my Windows Go. Finally I managed to go past the old format of the Subprocess with this command to start outfile in notepad in windows. The wait constant parameter mentioned in one manual did not exist so I just left out Wait as the user will close the program by themself or leave it open to reuse.

    p, err := os.StartProcess(`c:\windows\system32\notepad.EXE`,
        []string{`c:\windows\system32\notepad.EXE`, outfile},
        &os.ProcAttr{Env: nil, Dir: "", Files:  []*os.File{os.Stdin, os.Stdout, os.Stderr}})
    

    You would change the os.Stdout.. to os.Pipe as previous answer

    EDIT: I got it finally from godoc os Wait, that Wait has changed to method of and I succeeded to do:

       defer p.Wait(0)
    

    Then I decided finally to put

       defer p.Release()
    

    instead.

    0 讨论(0)
  • 2020-12-04 10:46

    This answer does not represent the current state of the Go standard library. Please take a look at @Lourenco's answer for an up-to-date method!


    Your example does not actually read the data from stdout. This works for me.

    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 讨论(0)
  • 2020-12-04 10:49

    The package "exec" was changed a little bit. The following code worked for me.

    package main
    
    import "os/exec"
    import . "fmt"
    
    func main() {
        app := "echo"
    
        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))
    }
    

    I hope this helps!

    0 讨论(0)
  • 2020-12-04 10:52
    
    import (
        "github.com/go-cmd/cmd"
    )
    
    const DefaultTimeoutTime = "1m"
    
    func RunCMD(name string, args ...string) (err error, stdout, stderr []string) {
        c := cmd.NewCmd(name, args...)
        s := <-c.Start()
        stdout = s.Stdout
        stderr = s.Stderr
        return
    }
    
    

    go test

    import (
        "fmt"
        "gotest.tools/assert"
        "testing"
    )
    
    func TestRunCMD(t *testing.T) {
        err, stdout, stderr := RunCMD("kubectl", "get", "pod", "--context", "cluster")
        assert.Equal(t, nil, err)
        for _, out := range stdout {
            fmt.Println(out)
        }
        for _, err := range stderr {
            fmt.Println(err)
        }
    }
    
    
    0 讨论(0)
  • 2020-12-04 10:54

    Here is a simple function that will run your command and capture the error, stdout, and stderr for you to inspect. You can easily see anything that might go wrong or be reported back to you.

    // 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
    }
    

    You can use it like this (Converting a media file):

    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)
    }
    

    I've used this with Go 1.2-1.7

    0 讨论(0)
提交回复
热议问题