Groovy 作為 JVM 上的動態語言,無縫調用 Java API、語法極簡,是替代 Windows .bat / Linux .sh 的最佳選擇。本文通過實例演示 Groovy 執行系統命令、指定工作目錄、進程等待與超時控制、輸入輸出流處理、大量輸出緩衝區消費等核心技巧,助力開發者構建自動化腳本庫。
// test.groovy
println 'cmd /c dir'.execute().text
// 執行: groovy test.groovy
// 等同於 Java: Runtime.getRuntime().exec("cmd /c dir")
String.execute() 返回 Process 對象,.text 讀取標準輸出並關閉流。
// 在 D:\project\mystudy2 下執行 dir
println 'cmd /c dir'.execute(null, new File("D:\\project\\mystudy2")).text
// execute(String[] envp, File dir) — envp 為 null 繼承當前環境變量
def proc = 'cmd /c dir'.execute()
// 阻塞等待進程結束
proc.waitFor()
println proc.text
// 帶超時等待 (毫秒),超時返回 false 並可選 kill
if (!proc.waitForOrKill(5000)) {
println "進程超時,已強制終止"
}
def proc = 'some-command'.execute()
InputStream in = proc.in // 標準輸出流
InputStream err = proc.err // 錯誤流
OutputStream out = proc.out // 標準輸入流 (向進程寫入)
// 手動消費輸出流,防止緩衝區滿導致進程阻塞
def reader = new BufferedReader(new InputStreamReader(proc.in))
String line
while ((line = reader.readLine()) != null) {
println "輸出: $line"
}
proc.waitFor()
若進程產生大量輸出而 Java 端未及時讀取,系統管道緩衝區會滿,導致進程阻塞。兩種解決模式:
def outputBuffer = new StringBuffer()
def errorBuffer = new StringBuffer()
def zipProc = 'gzip -c'.execute()
def unzipProc = 'gunzip -c'.execute()
// 異步消費輸出到 StringBuffer,內部啟動守護線程讀取
unzipProc.consumeProcessOutput(outputBuffer, errorBuffer)
// 僅消費錯誤流
zipProc.consumeProcessErrorStream(errorBuffer)
// 向 zipProc 寫入數據
zipProc.out.withWriter { writer ->
writer.write("大量文本數據...")
}
zipProc.out.close()
zipProc.waitFor()
println "壓縮輸出大小: ${outputBuffer.length()}"
execute() 返回的對象實際是 java.lang.Process 子類 (ProcessImpl/UNIXProcess/Win32Process) 的 Groovy 動態代理。所有 Process 方法 (destroy、exitValue、isAlive 等) 均可直接調用。
scripts/ 目錄,納入版本控制。exec(cmd, dir, timeout)、execAsync(cmd, consumer)。cmd /c (Win) vs sh -c (Linux/Mac),可用 System.getProperty("os.name") 判斷。Groovy 以 'command'.execute() 極簡語法、原生 Java 互操作、強大的流處理擴展,成為 JVM 生態下自動化腳本的首選。掌握進程控制、流消費、超時處理三大核心技巧,即可將繁瑣的手動操作轉化為可復用、可維護的自動化腳本,真正實現「讓機器為自己干活」。