dtmbc1606 2016-10-25 19:02
浏览 55
已采纳

Go-使用goroutines执行一次Bash命令n次并存储并打印其结果

I'm pretty new to Golang in general and I'm trying to execute a bash command with its arguments n times, then, store the Output in a variable and Print it.

I'm able to do it just one time, or just using loops like the following:

package main

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


func main() {

    //Default Output
    var (
        cmdOut []byte
        err    error
    )

    //Bash Command
    cmd  := "./myCmd"
   //Arguments to get passed to the command
   args := []string{"arg1", "arg2", "arg3"}

    //Execute the Command
    if cmdOut, err = exec.Command(cmd, args...).Output(); err != nil {
        fmt.Fprintln(os.Stderr, "There was an error running "+cmd+" "+args[0]+args[1]+args[2], err)
        os.Exit(1)
    }
    //Store it
    sha := string(cmdOut)
    //Print it
    fmt.Println(sha)
}

This works just fine, I'm able to read the output easily.

Now, I would like to repeat this very same operation for n times, using goroutines.

I tried following the very same approach of the guy who answered How would you define a pool of goroutines to be executed at once in Golang? but I'm not able to make it work.

That's what I tried so far:

package main

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


func main() {

    //Bash Command
    cmd  := "./myCmd"
    //Arguments to get passed to the command
     args := []string{"arg1", "arg2", "arg3"}

    //Common Channel for the goroutines
    tasks := make(chan *exec.Cmd, 64)

    //Spawning 4 goroutines
    var wg sync.WaitGroup
    for i := 0; i < 4; i++ {
        wg.Add(1)
        go func() {
            for cmd := range tasks {
                cmd.Run()
            }
            wg.Done()
        }()
    }

    //Generate Tasks
    for i := 0; i < 10; i++ {
        tasks <- exec.Command(cmd, args...)
        //Here I should somehow print the result of the latter command
    }
    close(tasks)

    // wait for the workers to finish
    wg.Wait()

    fmt.Println("Done")

}

But, I don't really find out how to store the i-result of an executed command and print it.

How can I achieve this?

Thanks in advance, for any clarification on the question just leave a comment.

  • 写回答

1条回答 默认 最新

  • dpdkqls6399 2016-10-25 19:38
    关注

    so the following fixes your problem

    • you can call Cmd.Output() to get the output of the command. otherwise you could connect the Cmd.StdOutPipe pipe to a byte.Buffer for example and read from that.

    • your goroutine logic was wrong. it would only execute 4 times cause then the waitgroup would be Done() and main would exit. You are correct to close the channel from main to signal the workers to exit the for range loop. wg.Done should be called after that so i defered it.

    • when you execute anonymous functions with the go command try not to capture anything from the parent scope. it can lead to disaster. instead figure out which parameters you want and pass them to the function.

    `

    package main 
    
    import (
        "fmt"
        "os/exec"
        "sync"
    )
    func main() {
        cmd := "./foo.sh"
        //Arguments to get passed to the command
        args := []string{"bar", "baz"}
    
        //Common Channel for the goroutines
        tasks := make(chan *exec.Cmd, 64)
    
        //Spawning 4 goroutines
        var wg sync.WaitGroup
        for i := 0; i < 4; i++ {
                wg.Add(1)
                go func(num int, w *sync.WaitGroup) {
                        defer w.Done()
                        var (
                                out []byte
                                err error
                        )
                        for cmd := range tasks { // this will exit the loop when the channel closes
                                out, err = cmd.Output()
                                if err != nil {
                                        fmt.Printf("can't get stdout:", err)
                                }
                                fmt.Printf("goroutine %d command output:%s", num, string(out))
                        }
                }(i, &wg)
        }
        //Generate Tasks
        for i := 0; i < 10; i++ {
                tasks <- exec.Command(cmd, args...)
        }
        close(tasks)
    
        // wait for the workers to finish
        wg.Wait()
    
        fmt.Println("Done")
    
    }
    

    `

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 pyqt6如何引用qrc文件加载里面的的资源
  • ¥15 安卓JNI项目使用lua上的问题
  • ¥20 RL+GNN解决人员排班问题时梯度消失
  • ¥15 统计大规模图中的完全子图问题
  • ¥15 使用LM2596制作降压电路,一个能运行,一个不能
  • ¥60 要数控稳压电源测试数据
  • ¥15 能帮我写下这个编程吗
  • ¥15 ikuai客户端l2tp协议链接报终止15信号和无法将p.p.p6转换为我的l2tp线路
  • ¥15 phython读取excel表格报错 ^7个 SyntaxError: invalid syntax 语句报错
  • ¥20 @microsoft/fetch-event-source 流式响应问题