Java & Groovy & Scala & Kotlin - 32.Sehll

Overview

本章主要介紹如何通過(guò)這幾種語(yǔ)言來(lái)執(zhí)行 Shell 命令。

Java

執(zhí)行 Shell 命令

Java 中執(zhí)行 Shell 命令主要依靠 Runtime 和 Process 兩個(gè)類(lèi)。

例:

 try {
    Runtime runtime = Runtime.getRuntime();
    Process process = runtime.exec("ls -al ..");
    //  等待 Shell 執(zhí)行的結(jié)果,0 為正常執(zhí)行完畢
    int exitValue = process.waitFor();
    if (exitValue != 0) {
        System.out.println("exit with " + exitValue);
        return;
    }
    //  輸出 Shell 執(zhí)行的結(jié)果
    try (InputStream in = process.getInputStream();
         InputStreamReader isr = new InputStreamReader(in);
         BufferedReader reader = new BufferedReader(isr)) {
        String line;
        while ((line = reader.readLine()) != null) {
            System.out.println(line);
        }
    }

} catch (Exception e) {
    e.printStackTrace();
}

以上例子可以看到在 Java 中執(zhí)行 Shell 命令還是比較復(fù)雜的,簡(jiǎn)單的 ls 也需要不少代碼,不過(guò)其中大部分都是普通的 IO 流操作。

Pipe 操作

Pipe 操作在 Shell 命令中非常常見(jiàn),可惜的是 Java 無(wú)法直接通過(guò)執(zhí)行 Shell 命令來(lái)實(shí)現(xiàn)此功能,而必須使用執(zhí)行腳本的方式才能正常執(zhí)行。

例:

try {
    Runtime runtime = Runtime.getRuntime();
    String[] cmd = {"/bin/sh", "-c", "ls -al .. | grep JGSK"};
    Process process = runtime.exec(cmd);

    int exitValue = process.waitFor();
    if (exitValue != 0) {
        System.out.println("exit with " + exitValue);
        return;
    }

    try (InputStream in = process.getInputStream();
         InputStreamReader isr = new InputStreamReader(in);
         BufferedReader reader = new BufferedReader(isr)) {
        String line;
        while ((line = reader.readLine()) != null) {
            System.out.println(line);
        }
    }

} catch (Exception e) {
    e.printStackTrace();
}

相比較直接執(zhí)行命令而言,只是 runtime.exec() 這個(gè)方法的參數(shù)有了變化。

從控制臺(tái)讀取輸入

Scanner scanner = new Scanner(System.in);
System.out.println(scanner.nextLine());

Groovy

執(zhí)行 Shell 命令

Groovy 中對(duì) Java 的方法做了一些包裝,使用起來(lái)更加簡(jiǎn)單。

例:

def p = "ls -al ..".execute()
def exitValue = p.waitFor()
if (exitValue != 0) {
    println("exit with $exitValue")
    return
}
println "${p.text}"

Pipe 操作

Groovy 也無(wú)法直接在命令中執(zhí)行 Pipe 操作,但是卻提供了 pipe() 方法用以連接兩個(gè) Process。

例:

def p1 = "ls -al ..".execute()
def p2 = "grep JGSK".execute()
def p3 = p1.pipeTo(p2)
exitValue = p3.waitFor()
if (exitValue != 0) {
    println("exit with $exitValue")
    return
}
println "${p3.text}"

從控制臺(tái)讀取輸入

例:

def scanner = new Scanner(System.in)
println(scanner.nextLine())

Scala

執(zhí)行 Shell 命令

Scala 執(zhí)行 Shell 命令只要使用 ! 方法就可以了。

val exitValue = "ls -al .." !

以上例子會(huì)進(jìn)行阻塞并返回執(zhí)行結(jié)果,0 表示正常執(zhí)行完畢。

val result = "ls -al .." !!

以上例子會(huì)進(jìn)行阻塞并返回執(zhí)行完畢的輸出結(jié)果,如果沒(méi)有正常執(zhí)行完畢則拋出異常。

通過(guò)以上兩個(gè)例子可以看到 Scala 操作 Shell 簡(jiǎn)簡(jiǎn)單單一句話(huà)就可以搞定。

Pipe 操作

Scala 進(jìn)行 Pipe 操作非常接近實(shí)際在 Shell 中執(zhí)行的命令,只是使用 #| 替換了 |。

"ls -al .." #| "grep JGSK" !

實(shí)際上 # 可以與各種操作結(jié)合用在多種地方,比如說(shuō)文件的輸出。

"ls -al .." #> new File("shell.txt") !
"ls -al .." #>> new File("shell.txt") !

從控制臺(tái)讀取輸入

例:

println(StdIn.readLine())

Kotlin

執(zhí)行 Shell 命令

Kotlin 目前沒(méi)有自己的 Api,所以只能調(diào)用 Java 的方法。

例:

val runtime: Runtime = Runtime.getRuntime()
val process: Process = runtime.exec("ls -al ..")
val exitValue = process.waitFor()
if (exitValue != 0) {
    println("exit with $exitValue")
    return
}

process.inputStream.bufferedReader().lines().forEach {
    println(it)
}

從控制臺(tái)讀取輸入

例:

println(readLine())

Summary

  • 各種語(yǔ)言都可以進(jìn)行 Shell 操作,但是只有 Scala 和 Groovy 的 api 具有實(shí)際生產(chǎn)力。

文章源碼見(jiàn) https://github.com/SidneyXu/JGSK 倉(cāng)庫(kù)的 _32_shell 小節(jié)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容