Java 通過 Runtime.exec() 或 ProcessBuilder 調用 Shell 腳本,可實現系統級操作(如 FTP 傳輸、備份腳本)。本文提供完整的工具類與 Shell 腳本示例,涵蓋日誌記錄、參數傳遞、異常處理。
import java.io.*;
import java.text.SimpleDateFormat;
import java.util.Date;
public class ShellExecutor {
private static final String LOG_FILE = "/tmp/executeShell.log";
/**
* 執行 Shell 命令並記錄日誌
* @param command 完整命令,如 "sh /tmp/send.sh /data/file.txt"
* @return 0 失敗,1 成功
*/
public int execute(String command) {
StringBuilder log = new StringBuilder();
String timestamp = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
log.append(timestamp).append(" 準備執行: ").append(command).append("\n");
Process process = null;
BufferedReader reader = null;
try {
// 使用 /bin/sh -c 支援管道、重定向等 Shell 特性
process = Runtime.getRuntime().exec(new String[]{"/bin/sh", "-c", command});
log.append("進程 PID: ").append(process.pid()).append("\n");
reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
int exitCode = process.waitFor();
log.append(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()))
.append(" 執行結束, 退出碼: ").append(exitCode).append("\n輸出:\n");
String line;
while ((line = reader.readLine()) != null) {
log.append(line).append("\n");
}
return (exitCode == 0) ? 1 : 0;
} catch (Exception e) {
log.append("異常: ").append(e.getMessage()).append("\n");
return 0;
} finally {
closeQuietly(reader);
writeLog(log.toString());
}
}
private void writeLog(String content) {
try (FileWriter fw = new FileWriter(LOG_FILE, true); // 追加模式
BufferedWriter bw = new BufferedWriter(fw)) {
bw.write(content);
} catch (IOException ignored) {}
}
private void closeQuietly(Closeable c) {
if (c != null) try { c.close(); } catch (IOException ignored) {}
}
}
#!/bin/sh
# send_to_kondor.sh
# 參數: $1=本地文件目錄 $2=文件名
LOG="/var/log/send_kondor.log"
KONDOR_IP="192.168.1.200"
FTP_USER="kondor"
FTP_PASS="kondor"
log() { echo "[$(date '+%F %T')] $*" | tee -a "$LOG"; }
[ $# -lt 2 ] && { log "用法: $0 <目錄> <文件名>"; exit 1; }
DIR=$1; FILE=$2
cd "$DIR" || { log "目錄不存在: $DIR"; exit 1; }
[ -f "$FILE" ] || { log "文件不存在: $FILE"; exit 1; }
log "開始上傳 $FILE 到 $KONDOR_IP"
ftp -n "$KONDOR_IP" <
public class Main {
public static void main(String[] args) {
ShellExecutor executor = new ShellExecutor();
// 上傳 /data/report.txt 到 Kondor 系統
int result = executor.execute("sh /tmp/send_to_kondor.sh /data report.txt");
System.out.println(result == 1 ? "Shell 執行成功" : "Shell 執行失敗,請查日誌");
}
}
ProcessBuilder,支援目錄設置、環境變量、輸出重定向更靈活。getErrorStream(),否則緩衝區填滿導致進程阻塞。process.waitFor(timeout, TimeUnit.SECONDS) 防止掛死。public int executeModern(String... cmd) {
ProcessBuilder pb = new ProcessBuilder(cmd);
pb.redirectErrorStream(true); // 合併錯誤流到標準輸出
try {
Process p = pb.start();
try (BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream()))) {
String line;
while ((line = br.readLine()) != null) {
System.out.println(line); // 或寫日誌
}
}
return p.waitFor(30, TimeUnit.SECONDS) ? (p.exitValue() == 0 ? 1 : 0) : -1; // -1 超時
} catch (Exception e) {
return 0;
}
}
// 調用: executeModern("/bin/sh", "-c", "sh /tmp/send.sh /data file.txt");