将cmd stdout和stderr作为字符串返回,而不是打印到golang中的控制台

将cmd stdout和stderr作为字符串返回,而不是打印到golang中的控制台,go,Go,我正在从golang应用程序执行bash命令。现在stdout和stderr直接进入控制台: cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr 但是我希望stdout和stderr作为字符串变量从runbashcomandkilliftooslow函数返回,而无需立即打印到控制台。 如何实现这一点 守则: package main import ( "fmt" "log" "os" "os/exec" "ti

我正在从
golang
应用程序执行bash命令。现在
stdout
stderr
直接进入控制台:

cmd.Stdout = os.Stdout 
cmd.Stderr = os.Stderr
但是我希望
stdout
stderr
作为字符串变量从
runbashcomandkilliftooslow
函数返回,而无需立即打印到控制台。 如何实现这一点

守则:

package main

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

func main() {
    ok, outString, errString := runBashCommandAndKillIfTooSlow("ls -la", 2000)
    fmt.Println("ok")
    fmt.Println(ok)
    fmt.Println("outString")
    fmt.Println(outString)
    fmt.Println("errString")
    fmt.Println(errString)
}

/*
run bash command and kill it if it works longer than "killInMilliSeconds" milliseconds
*/
func runBashCommandAndKillIfTooSlow(command string, killInMilliSeconds time.Duration) (okResult bool, stdout, stderr string) {
    fmt.Println("running bash command...")
    fmt.Println(command)
    cmd := exec.Command("sh", "-c", command)

    cmd.Stdout = os.Stdout // cmd.Stdout -> stdout
    cmd.Stderr = os.Stderr // cmd.Stderr -> stderr

    okResult = true

    err := cmd.Start()
    log.Printf("Waiting for command to finish...")
    done := make(chan error, 1)
    go func() {
        done <- cmd.Wait()
    }()
    select {
    case <-time.After(killInMilliSeconds * time.Millisecond):
        if err := cmd.Process.Kill(); err != nil {
            log.Fatal("failed to kill: ", err)
            okResult = false
        }
        <-done // allow goroutine to exit
        // log.Println("process killed")
    case err := <-done:

        if err != nil {
            log.Printf("process done with error = %v", err)
            okResult = false
        }
    }
    if err != nil {
        log.Fatal(err)
        okResult = false
    }
    return
}
主程序包
进口(
“fmt”
“日志”
“操作系统”
“os/exec”
“时间”
)
func main(){
ok,outString,errString:=runbashcomandkilliftooslow(“ls-la”,2000)
fmt.Println(“确定”)
fmt.Println(正常)
fmt.Println(“突出”)
fmt.Println(外伸)
格式打印项次(“错误字符串”)
fmt.Println(errString)
}
/*
运行bash命令,并在其工作时间超过“killinmilluses”毫秒时将其杀死
*/
func runBashCommandAndKillIfTooSlow(命令字符串,killin毫秒时间.Duration)(okResult bool,stdout,stderr字符串){
fmt.Println(“运行bash命令…”)
fmt.Println(命令)
cmd:=exec.Command(“sh”,“-c”,Command)
cmd.Stdout=os.Stdout//cmd.Stdout->Stdout
cmd.Stderr=os.Stderr//cmd.Stderr->Stderr
okResult=true
错误:=cmd.Start()
Printf(“等待命令完成…”)
完成:=生成(chan错误,1)
go func(){
完成将输出设置为a(在Go版本1.10或更高版本中)或a

运行命令后,可以通过调用以下方法将stdout和stderr作为字符串获取:


您可以使用
cmd.Run()
而不是
cmd.Start()
使其自动等待完成,并使用
exec.CommandContext()
使其超时。这也将以正确的顺序输出,而原始程序由于go例程而无法正常运行

下面是使用@Mello Marmot的答案简化的完全相同的程序:

package main

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

    "golang.org/x/net/context"
)

func main() {
    ctx := context.Background()
    ok, outString, errString := runBashCommandAndKillIfTooSlow(ctx, "ls -la", 2000*time.Millisecond)
    fmt.Println("ok")
    fmt.Println(ok)
    fmt.Println("outString")
    fmt.Println(outString)
    fmt.Println("errString")
    fmt.Println(errString)
}

/*
run bash command and kill it if it works longer than "killIn"
*/
func runBashCommandAndKillIfTooSlow(ctx context.Context, command string, killIn time.Duration) (okResult bool, stdout, stderr string) {
    fmt.Println("running bash command...")
    fmt.Println(command)
    ctx, _ = context.WithTimeout(ctx, killIn)
    cmd := exec.CommandContext(ctx, "sh", "-c", command)

    // Set output to Byte Buffers
    var outb, errb bytes.Buffer
    cmd.Stdout = &outb
    cmd.Stderr = &errb

    okResult = true
    err := cmd.Run()
    stdout = outb.String()
    stderr = errb.String()
    if err != nil {
        log.Fatal(err)
        okResult = false
    }
    return
}

另一个选项是
strings.Builder

package main

import (
   "os/exec"
   "strings"
)

func main() {
   b := new(strings.Builder)
   c := exec.Command("go", "version")
   c.Stdout = b
   c.Run()
   println(b.String() == "go version go1.16.3 windows/amd64\n")
}

package main

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

    "golang.org/x/net/context"
)

func main() {
    ctx := context.Background()
    ok, outString, errString := runBashCommandAndKillIfTooSlow(ctx, "ls -la", 2000*time.Millisecond)
    fmt.Println("ok")
    fmt.Println(ok)
    fmt.Println("outString")
    fmt.Println(outString)
    fmt.Println("errString")
    fmt.Println(errString)
}

/*
run bash command and kill it if it works longer than "killIn"
*/
func runBashCommandAndKillIfTooSlow(ctx context.Context, command string, killIn time.Duration) (okResult bool, stdout, stderr string) {
    fmt.Println("running bash command...")
    fmt.Println(command)
    ctx, _ = context.WithTimeout(ctx, killIn)
    cmd := exec.CommandContext(ctx, "sh", "-c", command)

    // Set output to Byte Buffers
    var outb, errb bytes.Buffer
    cmd.Stdout = &outb
    cmd.Stderr = &errb

    okResult = true
    err := cmd.Run()
    stdout = outb.String()
    stderr = errb.String()
    if err != nil {
        log.Fatal(err)
        okResult = false
    }
    return
}
package main

import (
   "os/exec"
   "strings"
)

func main() {
   b := new(strings.Builder)
   c := exec.Command("go", "version")
   c.Stdout = b
   c.Run()
   println(b.String() == "go version go1.16.3 windows/amd64\n")
}