简体   繁体   English

有没有办法将 bash 脚本的标准输出存储到 GO 中的变量中?

[英]Is there a way to store stdout from a bash script into a variable within GO?

I'm running a really simple bash script which just echo's some data within Go. I've placed this into a wrapper and used the exec package to execute this.我正在运行一个非常简单的 bash 脚本,它只是回显 Go 中的一些数据。我将其放入包装器中并使用 exec package 来执行它。 This works nicely by outputting to my terminal, however, I can't find any way to actually store this into a variable in Go.这通过输出到我的终端很好地工作,但是,我找不到任何方法将它实际存储到 Go 中的变量中。

I'm new to Go, so my debugging skills aren't amazing.我是 Go 的新手,所以我的调试技巧并不惊人。 However, I've placed some basic logging outputs to try to narrow down where exactly I need to get the output from, but to no avail.但是,我已经放置了一些基本的日志记录输出以尝试缩小我需要从中获取 output 的确切位置,但无济于事。

The two functions which run bash:运行 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()), ""
}

This is the function to fake test my bash script:这是 function 假测试我的 bash 脚本:

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

The echo happens between flag 1 & 2 and at any point when I try to log any values from cmd/stdout I get empty strings.回声发生在标志 1 和 2 之间,并且在我尝试从 cmd/stdout 记录任何值时的任何时候我都会得到空字符串。 Within the main function, the result variable produces: 2020/06/19 18:17:14 Result: %!(EXTRA string=)在主 function 中,结果变量产生: 2020/06/19 18:17:14 Result: %!(EXTRA string=)

So I suppose my first question is why isn't result (which is in theory string(stdout.Bytes())) not producing the echo?所以我想我的第一个问题是为什么结果(理论上是字符串(stdout.Bytes()))不产生回声? & Secondly, where/how can I save the output to a variable? &其次,在哪里/如何将 output 保存到变量?

Thanks & feel free to ping me if I've missed any questions &/or need more details谢谢,如果我遗漏了任何问题和/或需要更多详细信息,请随时联系我

--Edit: Also forgot to mention, the code was heavily inspired by this Kube.netes go script. --编辑:还忘了说,代码很大程度上受到了这个Kube.netes go 脚本的启发。 If there are any recommendations/criticism to doing it this way, I'd be really happy to hear/learn:)如果对这样做有任何建议/批评,我会很高兴听到/学习:)

Question 1:问题一:

stdout and stderr are never assigned to cmd in your code.在您的代码中,stdout 和 stderr 永远不会分配给 cmd。

try this:试试这个:

cmd.Stdout = stdout
cmd.Stderr = stderr

alternatively, try this simpler version:或者,试试这个更简单的版本:

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

Finally, you can "proxy" to os.Stdout最后,你可以“代理”到 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)
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM