从命令exec实时捕获stdout

时间:2018-01-20 07:32:44

标签: go

我目前正在开发一个可以执行命令的聊天机器人。我希望它做的一件事是能够运行脚本并将脚本的标准输出输出到聊天中。

我遇到的问题是该函数收集脚本的所有stdout并在最后返回它们,我想尝试修改它以实时写入并且遇到了问题。

我认为问题可能涉及的是,只有一种方法可以将文本返回到聊天频道,即通过重启的返回功能。但是,如果可能的话,我想迭代exec命令并输出。

这是我的代码:

func reboot(command *bot.Cmd) (string, error) {
    n := command.Args[0]
    // this return is what all gets sent into chat channel
    return runcommand(n), nil
  }


func runcommand(server string) string {
    cmd := exec.Command("/bin/bash", "-c", "python test.py %s", server)
    cmdOutput := &bytes.Buffer{}
    cmd.Stdout = cmdOutput
    err := cmd.Run()
    if err !=nil {
        os.Stderr.WriteString(err.Error())
    }
        return fmt.Sprintf(string(cmdOutput.Bytes()))
}

2 个答案:

答案 0 :(得分:2)

redis.log的实时命令管道。 (您可以致电bgsave进行测试。)

package main

import (
    "os"
    "os/exec"
    "fmt"
    "bufio"
)

func main() {
    cmd := exec.Command("tail", "-f",  "/usr/local/var/log/redis.log")

    // create a pipe for the output of the script
    cmdReader, err := cmd.StdoutPipe()
    if err != nil {
        fmt.Fprintln(os.Stderr, "Error creating StdoutPipe for Cmd", err)
        return
    }

    scanner := bufio.NewScanner(cmdReader)
    go func() {
        for scanner.Scan() {
            fmt.Printf("\t > %s\n", scanner.Text())
        }
    }()

    err = cmd.Start()
    if err != nil {
        fmt.Fprintln(os.Stderr, "Error starting Cmd", err)
        return
    }

    err = cmd.Wait()
    if err != nil {
        fmt.Fprintln(os.Stderr, "Error waiting for Cmd", err)
        return
    }
}

答案 1 :(得分:-1)

我还没有找到解决问题的方法,但我发现了一些奇怪的事情。

我写了一个程序的三个版本,它重复输出一个间隔一秒的短字符串,一个在Python中,一个在C中,一个在Go中:

talker.py

import time

while True:
        print("Now!")
        time.sleep(1)

talker.c

#include <unistd.h>

main() {
        for(;;) {
                write(1, "Now!\n", 5);
                sleep(1);
        }
}

talker.go

package main

import (
        "fmt"
        "time"
)

func main() {
        for {
                fmt.Println("Now!")
                time.Sleep(time.Second)
        }
}

当我自己运行它们(例如python ./talker.py)时,它们似乎完全相同。但是当我将输出传递给cat时,我看到了一个区别; C和Go版本立即将其输出传递到屏幕,但不是Python版本。它的输出被缓冲,并且在收集到足够的数据之前不会显示在屏幕上。

我甚至尝试使用cat的简单Go版本,但这并没有改变行为:

package main

import (
        "io"
        "os"
)

func main() {
        io.Copy(os.Stdout, os.Stdin)
}