如何用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
原代码失效原因
- 原代码仅读取了主进程(yarn)的标准输出流,而prettier的警告、错误信息输出到了标准错误流,未被捕获;
- 若子进程输出内容较多,缓冲区满后会被阻塞,无法继续输出,导致部分内容丢失。
内容的提问来源于stack exchange,提问作者basse
相关产品推荐
相关产品推荐

