doubi1818 2018-02-18 08:00
浏览 13
已采纳

运行命令并在线输出

I use the following code which works, The problem is that the output is printed just as the process finished to execute, I want to print to the screen the output live and not provide all the output when the process finishes, how can I achieve this?

cmdParams := [][]string{
    {filepath.Join(dir,path), "npm", "install"},
    {filepath.Join(pdir,n.path), "gulp"},
}

for _, cp := range cmdParams {
    log.Printf("Starting %s in folder %s...", cp[1:], cp[0])
    cmd := exec.Command(cp[1], cp[2:]...)
    cmd.Dir = cp[0]
    // Wait to finish, get output:
    out, err := cmd.Output()
    if err != nil {
        log.Printf("Error running %s: %v
", cp[1:], err)
        return
    }
    log.Println("Finished %s, output: %s", cp[1:], out)
}

update when trying the proposed solution I got the output like

2018/02/18 11:11:57  Starting [npm install] in folder ...
2018/02/18 11:12:14 adde
2018/02/18 11:12:14 d 56
2018/02/18 11:12:14 3 pa
2018/02/18 11:12:14 ckag
2018/02/18 11:12:14 es i
2018/02/18 11:12:14 n 15
2018/02/18 11:12:14 .477
2018/02/18 11:12:14 s
2018/02/18 11:12:14 Finished %s [npm install]
  • 写回答

1条回答 默认 最新

  • doujin8476 2018-02-18 08:35
    关注

    Using the solution presented in this answer: Streaming commands output progress

    cmdParams := [][]string{
        {filepath.Join(dir, path), "npm", "install"},
        {filepath.Join(pdir, n.path), "gulp"},
    }
    for _, cp := range cmdParams {
        log.Printf("Starting %s in folder %s...", cp[1:], cp[0])
        cmd := exec.Command(cp[1], cp[2:]...)
        cmd.Dir = cp[0]
    
        stdout, err := cmd.StdoutPipe()
        if err != nil {
            log.Printf("%s cmd.StdoutPipe() error: %v
    ", cp[1:], err)
            return
        }
        // Start command:
        if err = cmd.Start(); err != nil {
            log.Printf("%s start error: %v
    ", cp[1:], err)
            return
        }
    
        // Stream command output:
        scanner := bufio.NewScanner(stdout)
        scanner.Split(bufio.ScanRunes)
        for scanner.Scan() {
            fmt.Print(scanner.Text())
        }
        if scanner.Err() != nil {
            log.Printf("Reading %s stdout error: %v
    ", cp[1:], err)
            return
        }
    
        // Get execution success or failure:
        if err = cmd.Wait(); err != nil {
            log.Printf("Error running %s: %v
    ", cp[1:], err)
            return
        }
        log.Printf("Finished %s", cp[1:])
    }
    

    Some explanation:

    This line:

    scanner := bufio.NewScanner(stdout)
    

    Creates a bufio.Scanner that will read from the pipe that supplies the output written by the process.

    This line:

    scanner.Split(bufio.ScanRunes)
    

    Instructs the scanner to read the input by runes instead of the default by-lines.

    Note that the above example only streams the standard output of the process. If you also need its standard error stream, you could also read from Command.StderrPipe().

    Also note that this won't work with some commands that don't write everything to their standard output or error. For details, see How to get the realtime output for a shell command in golang?

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

报告相同问题?

悬赏问题

  • ¥15 企业资源规划ERP沙盘模拟
  • ¥15 树莓派控制机械臂传输命令报错,显示摄像头不存在
  • ¥15 前端echarts坐标轴问题
  • ¥15 CMFCPropertyPage
  • ¥15 ad5933的I2C
  • ¥15 请问RTX4060的笔记本电脑可以训练yolov5模型吗?
  • ¥15 数学建模求思路及代码
  • ¥50 silvaco GaN HEMT有栅极场板的击穿电压仿真问题
  • ¥15 谁会P4语言啊,我想请教一下
  • ¥15 这个怎么改成直流激励源给加热电阻提供5a电流呀