【问题标题】:Is there a way to store stdout from a bash script into a variable within GO?有没有办法将 bash 脚本中的标准输出存储到 GO 中的变量中?
【发布时间】:2020-06-20 01:57:08
【问题描述】:

我正在运行一个非常简单的 bash 脚本,它只是在 Go 中回显一些数据。我已将其放入包装器中并使用 exec 包执行此操作。这可以通过输出到我的终端很好地工作,但是,我找不到任何方法将其实际存储到 Go 中的变量中。

我是 Go 新手,所以我的调试技能并不出色。但是,我已经放置了一些基本的日志输出来尝试缩小我需要从哪里获取输出,但无济于事。

运行 bash 的两个函数:

func main(){
    _, result,_ := runBash()
    log.Printf("Result: ", result)
}


func runBash()(bool, string, string){
    cmd := exec.Command("/bin/sh", "-s")
    cmd.Stdin = strings.NewReader(replicateRouter())
    return finishRunning(cmd)
}

func finishRunning(cmd *exec.Cmd) (bool, string, string) {
    log.Printf("Running: ")
    stdout, stderr := bytes.NewBuffer(nil), bytes.NewBuffer(nil)
    cmd.Stdout = os.Stdout
    cmd.Stderr = os.Stderr
    done := make(chan struct{})
    defer close(done)
    go func() {
        for {
            select {
            case <-done:
                return
            case s := <-signals:
                cmd.Process.Signal(s)
            }
        }
    }()
    log.Printf("Flag 1")
    if err := cmd.Run(); err != nil {
        log.Printf("Error running %v", err)
        return false, string(stdout.Bytes()), string(stderr.Bytes())
    }
    log.Printf("Flag 2")
    return true, string(stdout.Bytes()), ""
}

这是伪造测试我的 bash 脚本的函数:

func replicateRouter() string{
    return `echo <HOSTNAME> <IP> <MACADDRESS>`
}

回显发生在标志 1 和 2 之间,当我尝试从 cmd/stdout 记录任何值时,我得到空字符串。在主函数中,结果变量产生: 2020/06/19 18:17:14 Result: %!(EXTRA string=)

所以我想我的第一个问题是为什么结果(理论上是字符串(stdout.Bytes()))不产生回声? & 其次,我在哪里/如何将输出保存到变量中?

谢谢,如果我遗漏了任何问题和/或需要更多详细信息,请随时联系我

--编辑: 另外忘了提一下,代码很大程度上受到了thisKubernetes go script 的启发。如果有任何建议/批评这样做,我会很高兴听到/学习:)

【问题讨论】:

  • 错字?使用 stderr 和 stdout 代替 os.Stderr 和 os.Stdin。
  • 是的,没错。一旦我删除 os.Stderr/&Stdin 并替换它们,它就会立即工作。我认为使用 os.stderr/in 是如何在不使用 Go 中的 logging/fmt 的情况下将其实际打印到终端。但是我们每天都会学到一些新东西:)

标签: linux bash go


【解决方案1】:

问题一:

stdout 和 stderr 永远不会在您的代码中分配给 cmd。

试试这个:

cmd.Stdout = stdout
cmd.Stderr = stderr

或者,试试这个更简单的版本:

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

最后,你可以“代理”到 os.Stdout

package main

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


func main() {
    stdout := new(bytes.Buffer)
    stderr := new(bytes.Buffer)
    _, _ = io.Copy(os.Stdout, stdout)
    _, _ = io.Copy(os.Stderr, stderr)

    cmd  := exec.Command("date")
    cmd.Stdout = stdout
    cmd.Stderr = stderr
    cmd.Run()



    output := string(stdout.Bytes())
    fmt.Printf("The date is %s\n", output)
}

【讨论】:

  • 非常感谢,你说得对,我忘了在代码中的任何位置分配 stdout 和 stderr。现在我做到了,我能够成功地将它放入 Result。我会尝试另一种方法。再次感谢,这让我很生气!
猜你喜欢
  • 2021-07-05
  • 2012-04-03
  • 1970-01-01
  • 2021-07-04
  • 1970-01-01
  • 1970-01-01
  • 2016-07-10
  • 2022-07-29
  • 1970-01-01
相关资源
最近更新 更多