You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Groovy捕获shell命令启动子进程的控制台输出?

在Groovy中捕获shell命令子进程的完整输出

问题重现

通过Groovy执行yarn prettier --check .时,期望捕获和直接在shell中执行完全一致的输出(包含yarn和prettier的所有标准输出、标准错误内容),但原代码仅能捕获yarn的部分输出,缺失了prettier的警告及错误信息。

原代码:

def check = "yarn prettier --check .".execute()
check.waitFor()
println check.getText()

原输出缺失prettier关键内容:

yarn run v1.22.17
$ /my-project/node_modules/.bin/prettier --check .
Checking formatting...
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.

解决方案

方法1:同时读取标准输出和标准错误(跨平台推荐)

问题核心是prettier的警告、错误信息输出到了标准错误流,且若不实时读取流内容,缓冲区满会导致子进程阻塞。通过线程分别读取两个流,确保捕获所有内容:

def process = "yarn prettier --check .".execute()
def fullOutput = new StringBuilder()

// 启动线程读取标准输出
def stdoutThread = Thread.start {
    process.inputStream.eachLine { line ->
        fullOutput.append(line).append("\n")
        // 可选:实时打印输出,和shell执行体验一致
        println line
    }
}

// 启动线程读取标准错误
def stderrThread = Thread.start {
    process.errorStream.eachLine { line ->
        fullOutput.append(line).append("\n")
        println line
    }
}

// 等待读取线程完成,再等待进程结束
stdoutThread.join()
stderrThread.join()
process.waitFor()

// 获取完整合并输出
println "\n=== 完整捕获的输出 ==="
println fullOutput.toString()

方法2:通过Shell合并输出(简洁,依赖系统Shell)

利用Shell重定向语法2>&1,将标准错误流合并到标准输出流,让Groovy可以一次性读取所有内容:

// Linux/macOS环境使用bash
def process = ["bash", "-c", "yarn prettier --check . 2>&1"].execute()
// Windows环境替换为:["cmd", "/c", "yarn prettier --check . 2>&1"].execute()
process.waitFor()
println process.text

原代码失效原因

  1. 原代码仅读取了主进程(yarn)的标准输出流,而prettier的警告、错误信息输出到了标准错误流,未被捕获;
  2. 若子进程输出内容较多,缓冲区满后会被阻塞,无法继续输出,导致部分内容丢失。

内容的提问来源于stack exchange,提问作者basse

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 19:49:59