drby30217 2016-05-07 17:01
浏览 851

如何在golang中获取shell命令的实时输出?

I am trying to call shell command with os/exec in golang, that command will take some time, so I would like to retrieve the reatime output and print the processed output (a progressing ratio number).

package main

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

func main() {
    cmdName := "ffmpeg -i t.webm  -acodec aac -vcodec libx264  cmd1.mp4"
    cmdArgs := strings.Fields(cmdName)

    cmd := exec.Command(cmdArgs[0], cmdArgs[1:len(cmdArgs)]...)
    stdout, _ := cmd.StdoutPipe()
    cmd.Start()
    go print(stdout)
    cmd.Wait()
}

// to print the processed information when stdout gets a new line
func print(stdout io.ReadCloser) {
    r := bufio.NewReader(stdout)
    line, _, err := r.ReadLine()
    fmt.Println("line: %s err %s", line, err)
}

I want to have a function where can update the screen when the command print something,

The ffmpeg command output is as follows:

frame=  101 fps=0.0 q=28.0 size=      91kB time=00:00:04.13 bitrate= 181.2kbits/
frame=  169 fps=168 q=28.0 size=     227kB time=00:00:06.82 bitrate= 272.6kbits/
frame=  231 fps=153 q=28.0 size=     348kB time=00:00:09.31 bitrate= 306.3kbits/
frame=  282 fps=140 q=28.0 size=     499kB time=00:00:11.33 bitrate= 360.8kbits/

in fact, the above 4 line is the last line of ffmpeg command output which keeps changing, I want to print that change out, like

18%
44%
69%
100%

how could I achieve this?

  • 写回答

4条回答

  • doudu22272099831 2016-05-09 03:42
    关注

    I do find icza's solution that he mentioned in that post is quite useful, however it didn't't solve my problem.

    I did a little test as following:

    1, I write a script which print some info every second for ten times, here is the script.sh

    #!/bin/bash
    
    for i in {1..10}
    do
        echo "step " $i
        sleep 1s
    done
    

    2, read the stdout and extract the needed information from stdout and do some process to get the expected format, here is the code: package main

    import (
        "fmt"
        "os/exec"
        "regexp"
        "strconv"
        "strings"
    )
    
    func getRatio(text string) float32 {
        re1, _ := regexp.Compile(`step[\s]+(\d+)`)
        result := re1.FindStringSubmatch(text)
        val, _ := strconv.Atoi(result[1])
        return float32(val) / 10
    }
    
    func main() {
        cmdName := "ffmpeg -i t.webm  -acodec aac -vcodec libx264  cmd1.mp4"
        //cmdName := "bash ./script.sh"
        cmdArgs := strings.Fields(cmdName)
    
        cmd := exec.Command(cmdArgs[0], cmdArgs[1:len(cmdArgs)]...)
        stdout, _ := cmd.StdoutPipe()
        cmd.Start()
    
        oneByte := make([]byte, 10)
        for {
            _, err := stdout.Read(oneByte)
            if err != nil {
                break
            }
            progressingRatio := getRatio(string(oneByte))
            fmt.Printf("progressing  ratio %v 
    ", progressingRatio)
        }
    }
    

    This does work for my script.sh test, but for the ffmpeg command it doesn't work, in ffmpeg's case, nothing get printed and the process get finished (not stuck), I guess the way of writing data to stdout for ffmpeg is a little special (maybe no newline character at all, and I tried icza's solution, but it still doesn't work).

    评论

报告相同问题?

悬赏问题

  • ¥15 乘性高斯噪声在深度学习网络中的应用
  • ¥15 运筹学排序问题中的在线排序
  • ¥15 关于docker部署flink集成hadoop的yarn,请教个问题 flink启动yarn-session.sh连不上hadoop,这个整了好几天一直不行,求帮忙看一下怎么解决
  • ¥30 求一段fortran代码用IVF编译运行的结果
  • ¥15 深度学习根据CNN网络模型,搭建BP模型并训练MNIST数据集
  • ¥15 C++ 头文件/宏冲突问题解决
  • ¥15 用comsol模拟大气湍流通过底部加热(温度不同)的腔体
  • ¥50 安卓adb backup备份子用户应用数据失败
  • ¥20 有人能用聚类分析帮我分析一下文本内容嘛
  • ¥30 python代码,帮调试,帮帮忙吧