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