首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java 調用 Shell 腳本執行命令(含 FTP 文件傳輸實例)

     編輯:Java 相關知識

Java 通過 Runtime.exec() 或 ProcessBuilder 調用 Shell 腳本,可實現系統級操作(如 FTP 傳輸、備份腳本)。本文提供完整的工具類與 Shell 腳本示例,涵蓋日誌記錄、參數傳遞、異常處理。

Java 工具類

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) {}
    }
}

FTP 上傳 Shell 腳本

#!/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 執行失敗,請查日誌");
    }
}

關鍵最佳實踐

  1. 使用 ProcessBuilder:新代碼推薦 ProcessBuilder,支援目錄設置、環境變量、輸出重定向更靈活。
  2. 讀取錯誤流:必須同時讀取 getErrorStream(),否則緩衝區填滿導致進程阻塞。
  3. 超時控制:Java 8+ 可用 process.waitFor(timeout, TimeUnit.SECONDS) 防止掛死。
  4. 避免命令注入:參數嚴格校驗,不直接拼接用戶輸入到命令字符串。
  5. 權限最小化:執行 Shell 的系統用戶僅擁有必要權限(如只讀特定目錄、只連特定 FTP IP)。

ProcessBuilder 現代寫法(Java 8+)

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");
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved