依賴引入
<dependency>
<groupId>com.jcraft</groupId>
<artifactId>jsch</artifactId>
<version>0.1.55</version>
</dependency>
核心工具類
public final class SshExecutor {
private static final Logger log = LoggerFactory.getLogger(SshExecutor.class);
private Session session;
private final int timeout = 60_000;
public void connect(String host, String user, String password, int port) throws JSchException {
JSch jsch = new JSch();
session = jsch.getSession(user, host, port);
session.setPassword(password);
session.setConfig("StrictHostKeyChecking", "no"); // 生產建議改為 known_hosts 驗證
session.setTimeout(timeout);
session.connect();
log.info("SSH 連線建立:{}@{}", user, host);
}
public String exec(String command, String charset) throws JSchException, IOException {
ChannelExec channel = (ChannelExec) session.openChannel("exec");
channel.setCommand(command);
channel.setErrStream(System.err);
channel.connect();
try (InputStream in = channel.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(in, Charset.forName(charset)))) {
StringBuilder output = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
output.append(line).append('\n');
}
return output.toString();
} finally {
channel.disconnect();
}
}
public void disconnect() {
if (session != null && session.isConnected()) {
session.disconnect();
log.info("SSH 連線關閉");
}
}
}
使用範例
try (SshExecutor ssh = new SshExecutor()) {
ssh.connect("10.8.12.189", "jmuser", "root1234", 22);
String result = ssh.exec("java -version", "UTF-8");
System.out.println(result);
}
生產環境關鍵強化
- 金鑰認證替代密碼:
jsch.addIdentity(privateKeyPath) + session.setUserInfo
- Known Hosts 驗證:
jsch.setKnownHosts(knownHostsPath),移除 StrictHostKeyChecking=no
- 連線池化:搭配 Apache Commons Pool 2 管理 Session 物件,避免頻繁建立/銷毀
- 超時細分:連線超時、指令執行超時、閒置超時分別配置
- 日誌脫敏:輸出時過濾密碼、Token 等敏感資訊
常見異常排查
| 異常 | 可能原因 | 對策 |
| Auth fail | 密碼/金鑰錯誤、用戶無登入權限 | 檢查 /etc/ssh/sshd_config 的 PasswordAuthentication/PubkeyAuthentication |
| Connection timeout | 防火牆攔截、IP 錯誤、SSH 埠非 22 | telnet host port 驗證連通性 |
| Channel not opened | 伺服器禁止 Exec 通道 | 檢查 sshd_config PermitUserEnvironment、ForceCommand |