我們可以在命令行中執行各種命令,比如,創建文件、查看文件夾下文件、調用第三方工具等等。如果想在 java 代碼中執行命令應該怎麼操作呢?我們有兩種方式可以實現。 ...
by emanjusaka from https://www.emanjusaka.top/2024/03/java-exec-local-command 彼岸花開可奈何
本文歡迎分享與聚合,全文轉載請留下原文地址。
我們可以在命令行中執行各種命令,比如,創建文件、查看文件夾下文件、調用第三方工具等等。
如果想在 java 代碼中執行命令應該怎麼操作呢?我們有兩種方式可以實現:
- 通過Runtime.getRuntime().exec調用命令
- 使用ProcessBuilder類來構建和執行命令
Runtime.getRuntime().exec
Runtime.getRuntime().exec()是Java中用於執行操作系統命令的方法。它允許你在Java程式中執行外部命令,並獲取命令的輸出和錯誤信息。
下麵是使用Runtime.getRuntime().exec()執行一個簡單命令的步驟:
- 創建一個Runtime對象,通過調用Runtime.getRuntime()方法獲取。
- 調用exec()方法,傳入要執行的命令和參數。
- exec()方法返回一個Process對象,表示正在執行的進程。
- 使用Process對象的方法來獲取輸出、錯誤流和返回值。
/**
* 執行本地命令
* 不支持管道和重定向機制
*
* @param command 命令
*/
public static void executeLocalCommand(String command) {
try {
// 執行命令
Process process = Runtime.getRuntime().exec(command);
try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
BufferedReader errorReader = new BufferedReader(new InputStreamReader(process.getErrorStream()))) {
String line;
while ((line = reader.readLine()) != null) {
log.info(command + ",命令執行結果:", line);
}
while ((line = errorReader.readLine()) != null) {
// 輸出標準錯誤(stderr),標記為錯誤信息
if (line.startsWith("[ERROR]")) {
log.error(command + ",命令執行錯誤:", line);
} else {
log.warn(command + ",[WARNING]" + line);
}
}
// 等待命令執行完成
int exitCode = process.waitFor();
if (exitCode != 0) {
throw new ServiceException("執行命令失敗!");
}
}
} catch (IOException | InterruptedException e) {
Thread.currentThread().interrupt(); // 如果是InterruptedException,則重新設置中斷狀態
throw new RuntimeException(e);
}
log.info(command + ",命令執行成功");
}
註意:該方法不支持shell的管道符和重定向機制。它只能分步執行命令,每個命令都是獨立的進程。
在進程執行完成後,你應該調用Process對象的waitFor()方法來等待進程結束,並獲取進程的返回值。這樣可以確保進程正常結束,並且你可以根據返回值進行進一步處理。
如果需要使用管道符和重定向機制,可以考慮使用ProcessBuilder類來構建和執行命令。
ProcessBuilder
ProcessBuilder是Java中用於創建和控制操作系統進程的類。它比Runtime.exec()更加強大,因為它可以處理命令行參數、錯誤流和輸入流,並支持管道和重定向。
下麵是使用ProcessBuilder執行一個簡單命令的步驟:
- 創建一個ProcessBuilder對象,並傳入要執行的命令和參數。
- 調用start()方法啟動進程。
- 使用Process對象的方法來獲取輸出、錯誤流和返回值。
下麵是一個調用的示例:
package top.emanjusaka;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
@SpringBootApplication
public class Application {
public static void main(String[] args) {
String[] command = {
"ls",
"-l"
};
// 創建ProcessBuilder對象,並傳入要執行的命令和參數
ProcessBuilder processBuilder = new ProcessBuilder(command);
// 啟動進程
Process process = null;
try {
process = processBuilder.start();
// 獲取輸出流
try (
BufferedReader outputReader = new BufferedReader(new InputStreamReader(process.getInputStream()));
BufferedReader errorReader = new BufferedReader(new InputStreamReader(process.getErrorStream()));) {
String line;
while ((line = outputReader.readLine()) != null) {
System.out.println(line);
}
while ((line = errorReader.readLine()) != null) {
// 輸出標準錯誤(stderr),標記為錯誤信息
if (line.startsWith("[ERROR]")) {
System.out.println(command + ",命令執行錯誤:" + line);
} else {
System.out.println(command + ",[WARNING]" + line);
}
}
// 等待進程執行完成,並獲取返回值
int exitCode = process.waitFor();
System.out.println("Exit code: " + exitCode);
} catch (IOException e) {
throw new RuntimeException(e);
}
} catch (InterruptedException | IOException e) {
throw new RuntimeException(e);
}
}
}
執行結果:
上述代碼將執行ls -l命令,並將輸出列印到控制台。你可以根據需要修改命令和參數來執行其他命令或傳遞不同的參數。
請註意,使用ProcessBuilder時需要註意以下幾點:
- ProcessBuilder可以處理命令行參數,因此你可以通過將參數作為字元串數組傳遞給ProcessBuilder的構造函數來傳遞多個參數。
- 你可以使用redirectErrorStream(true)方法將錯誤流合併到輸出流中,這樣你就可以同時讀取標準輸出和錯誤輸出。
- 在進程執行完成後,你應該調用Process對象的waitFor()方法來等待進程結束,並獲取進程的返回值。這樣可以確保進程正常結束,並且你可以根據返回值進行進一步處理。
本文原創,才疏學淺,如有紕漏,歡迎指正。如果本文對您有所幫助,歡迎點贊,並期待您的反饋交流,共同成長。
原文地址: https://www.emanjusaka.top/2024/03/java-exec-local-command
微信公眾號:emanjusaka的編程棧