【问题标题】:How do you get the output of a system command in Go?如何在 Go 中获取系统命令的输出?
【发布时间】:2010-12-25 00:35:37
【问题描述】:

假设我想在 go 程序中运行 'ls',并将结果存储在字符串中。在 exec 和 os 包中似乎有一些 fork 进程的命令,但它们需要 stdout 等的文件参数。有没有办法将输出作为字符串获取?

【问题讨论】:

    标签: go


    【解决方案1】:

    如果你想要string 输出,strings.Builder 比 [1] 更有效 bytes.Buffer:

    package main
    
    import (
       "os/exec"
       "strings"
    )
    
    func main() {
       c, b := exec.Command("go", "version"), new(strings.Builder)
       c.Stdout = b
       c.Run()
       print(b.String())
    }
    
    1. https://golang.org/pkg/bytes#Buffer.String

    【讨论】:

      【解决方案2】:
      cmd := exec.Command("ls", "-al")
      output, _ := cmd.CombinedOutput()
      fmt.Println(string(output))
      

      cmd := exec.Command(name, arg...)
      stdout, err := cmd.StdoutPipe()
      cmd.Stderr = cmd.Stdout
      if err != nil {
          return err
      }
      if err = cmd.Start(); err != nil {
          return err
      }
      for {
          tmp := make([]byte, 1024)
          _, err := stdout.Read(tmp)
          fmt.Print(string(tmp))
          if err != nil {
              break
          }
      }
      

      【讨论】:

        【解决方案3】:
        推荐的答案 Go Language

        现在有一个更简单的方法:

        package main
        
        import (
            "fmt"
            "log"
            "os/exec"
        )
        
        func main() {
            out, err := exec.Command("date").Output()
            if err != nil {
                log.Fatal(err)
            }
            fmt.Printf("The date is %s\n", out)
        }
        

        out 是标准输出。它的格式为[]byte,但您可以轻松地将其更改为字符串:

        string(out)
        

        您也可以使用CombinedOutput() 代替Output(),后者返回标准输出和标准错误。

        exec.Command

        【讨论】:

        • 这很可能是现在公认的答案。接受的答案甚至不再编译。
        • 如果您不需要对命令执行任何其他操作(例如添加环境变量),则很有用。
        • 使用此代码的游乐场:play.golang.org/p/QM4JcIPrxJB
        【解决方案4】:

        我在最新版本的 GO (~1.11) 中使用了它

        // CmdExec Execute a command
        func CmdExec(args ...string) (string, error) {
        
            baseCmd := args[0]
            cmdArgs := args[1:]
        
            log.Debugf("Exec: %v", args)
        
            cmd := exec.Command(baseCmd, cmdArgs...)
            out, err := cmd.Output()
            if err != nil {
                return "", err
            }
        
            return string(out), nil
        }
        
        // Usage:
        // out, err := CmdExec("ls", "/home")
        

        【讨论】:

          【解决方案5】:

          编辑:此答案已过时。请参阅下面的Fatih Arslan's answer


          通过将Pipe 指定为标准输出来使用exec.Run(如果需要,还可以使用标准错误)。它将返回 cmd,其中在 Stdout(和 Stderr)字段中包含 os.File。然后您可以使用例如ioutil.ReadAll 来阅读它。

          例子:

          package main
          
          import (
              "exec";
              "io/ioutil";
          )
          
          func main() {
              if cmd, e := exec.Run("/bin/ls", nil, nil, exec.DevNull, exec.Pipe, exec.MergeWithStdout); e == nil {
                  b, _ := ioutil.ReadAll(cmd.Stdout)
                  println("output: " + string(b))
              }
          }
          

          【讨论】:

          • 我认为“exec”包已经不存在了。我必须使用下面 Fatih 列出的“os/exec”。
          • 投反对票原因:这个答案可能已经过时了,希望人们知道它。 exec 包不再存在 afaik,ioutil.ReadAll() 不再接受 cmd.Stdoutcmd.Stdin,因此关于这个答案的几乎所有内容都是错误和过时的。
          【解决方案6】:

          要将 stdout 和 stderr 都放入单独的字符串中,您可以像这样使用字节缓冲区:

          cmd := exec.Command("date")
          var outb, errb bytes.Buffer
          cmd.Stdout = &outb
          cmd.Stderr = &errb
          err := cmd.Run()
          if err != nil {
              log.Fatal(err)
          }
          fmt.Println("out:", outb.String(), "err:", errb.String())
          

          【讨论】:

            【解决方案7】:

            使用exec.Run,将管道传递给标准输出。从它返回的管道中读取。

            【讨论】:

            • 这应该被称为 exec.Run()(它返回一个 Cmd),而不是 Cmd.Run。
            【解决方案8】:

            两个选项,取决于您喜欢的范例:

            1. os.ForkExec()
            2. exec.Run()

            【讨论】:

              猜你喜欢
              • 2014-12-26
              • 2023-04-05
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2019-09-28
              • 2014-01-27
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多