在需要從 Java 程式遠端執行 Linux 指令、傳輸檔案或建立通道時,Ganymed SSH-2 是一個純 Java 實作、零外部依賴(含加密算法)、支援 SSH-2 完整功能(Shell、Port Forwarding、SCP/SFTP、X11 Forwarding)的輕量級選擇。本文以最小化範例示範如何建立連線、認證、執行指令並讀取結果。
com.ganymed):
<dependency>
<groupId>com.ganymed</groupId>
<artifactId>ganymed-ssh2</artifactId>
<version>262</version> <!-- 或更新版本 -->
</dependency>
new Connection(hostname) 建立連線物件conn.connect() 發起 TCP 連線並完成 SSH 協議握手conn.authenticateWithPassword(user, pass) 密碼認證(亦支援 Public Key)conn.openSession() 開啟會話通道session.execCommand(cmd) 執行遠端指令session.getStdout() 讀取標準輸出(建議用 StreamGobbler 處理流)session.getExitStatus() 取得退出碼import ch.ethz.ssh2.Connection;
import ch.ethz.ssh2.Session;
import ch.ethz.ssh2.StreamGobbler;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.IOException;
public class SshExecutor {
public static void main(String[] args) {
String hostname = "192.168.0.1";
String username = "root";
String password = "password";
try (Connection conn = new Connection(hostname)) {
conn.connect();
System.out.println("✅ TCP 連線與 SSH 握手成功");
boolean authenticated = conn.authenticateWithPassword(username, password);
if (!authenticated) throw new IOException("❌ 認證失敗,請檢查帳密或 SSH 伺服器設定");
System.out.println("✅ 認證通過");
try (Session sess = conn.openSession()) {
sess.execCommand("uname -a");
System.out.println("📋 遠端主機資訊:");
// 使用 StreamGobbler 正確處理輸出流(含 stderr 合併)
InputStream stdout = new StreamGobbler(sess.getStdout());
try (BufferedReader br = new BufferedReader(new InputStreamReader(stdout))) {
String line;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
}
Integer exitCode = sess.getExitStatus();
System.out.println("🏁 指令退出碼: " + (exitCode != null ? exitCode : "N/A"));
}
} catch (IOException e) {
e.printStackTrace();
System.exit(2);
}
}
}
✅ TCP 連線與 SSH 握手成功 ✅ 認證通過 📋 遠端主機資訊: Linux localhost.localdomain 2.6.22 #1 SMP Wed Aug 13 11:24:59 CST 2008 i686 i686 i386 GNU/Linux 🏁 指令退出碼: 0
session.startShell() 取代 execCommand,透過 stdin/stdout 實現持久終端機互動。conn.createLocalPortForwarder(localPort, targetHost, targetPort) 實現本地埠映射至遠端服務(如跳板機連資料庫)。SCPClient 或 SFTPClient 進行檔案上傳下載。conn.authenticateWithPublicKey(user, keyFile, keyPassphrase) 實現免密登入,提升自動化安全性。| 現象 | 原因 | 解決 |
|---|---|---|
| IOException: "Authentication method password not supported" | SSH 伺服器禁用密碼認證,僅允許公鑰 | 改用公鑰認證,或修改 sshd_config 開啟 PasswordAuthentication |
| 讀取 stdout 卡住/不完全 | 未處理 stderr,導致緩衝區塞滿 | 使用 StreamGobbler 同時消費 stdout/stderr,或合併讀取 |
| 中文亂碼 | 遠端 Locale 或 Java 預設編碼不一致 | 指定 new InputStreamReader(stdout, "UTF-8") 或遠端環境編碼 |
| 連線超時 | 防火牆/安全組阻擋 22 埠 | 檢查網路通達性、安全組規則、SSH 伺服器監聽地址 |
Ganymed SSH-2 雖已停止維護(最後更新 2015 年),但其純 Java、零依賴、API 簡潔的特性,使其在輕量級自動化腳本、舊系統維護、嵌入式環境中仍具不可替代的價值。新專案若需更活躍的社群與現代特性(如 ProxyJump、Ed25519 金鑰),可評估 JSch (仍活躍) 或 Apache MINA SSHD。