Loading... > 转载自:https://blog.csdn.net/zongf0504/article/details/88812983 java 领域中, 开源jar 包ganymed-ssh2 对ssh2协议进行了实现, 通过ganymed-ssh2 可实现Linux命令: ssh 和 scp 的功能. ganymed-ssh2 提供了多种认证方式, 可通过用户名密码, 秘钥等方式. 笔者常用的是用户名密码方式。 ganymed-ssh2 的开发步骤: 使用主机地址创建连接对象new Connection(host) 创建TCP连接, connection.connect() 进行身份认证,笔者使用的是用户名密码方式: connection.authenticateWithPassword(username, password) 创建会话,每次远程操作都需要重新打开一个会话. connection.openSession() 执行ssh 操作或scp 操作 关闭连接: connection.close() ## 引入maven 依赖 笔者习惯于使用maven 开发, 所以新建maven 项目, 然后引入依赖. 需要注意的是笔者使用的是build210 版本, 是buildxxx系列的最高版本. 不同版本的api 还是有差别的. ``` <dependencies> <!-- 引入ssh2 依赖 --> <dependency> <groupId>ch.ethz.ganymed</groupId> <artifactId>ganymed-ssh2</artifactId> <version>build210</version> </dependency> <!-- 引入单元测试 --> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> </dependency> </dependencies> ``` ## 开发工具类 ### 自定义SSH2 工具类 笔者觉得ganymed-ssh2 提供的API 并不符合笔者的开发习惯,所以进行了二次封装。 将常用的ssh2 操作封装成了一个工具类。 ``` import ch.ethz.ssh2.Connection; import ch.ethz.ssh2.SCPClient; import ch.ethz.ssh2.Session; import java.io.*; /** * @Description: ssh2 工具类 * @author: zongf * @date: 2019-03-25 20:23 */ public class SSH2Util { private static String DEFAULT_CHARSET = "UTF-8"; /** * @Description: 建立ssh2连接 * @param host 主机地址 * @param username 用户名 * @param password 密码 * @return: Connection * @author: zongf * @time: 2019-03-25 20:46:32 */ public static Connection openConnection(String host, String username, String password) { Connection connection; try { connection = new Connection(host); // 建立ssh2 连接 connection.connect(); // 校验用户名密码 boolean login = connection.authenticateWithPassword(username, password); // 登录成功返回连接 if (login) { return connection; }else { throw new RuntimeException("用户名密码不正确"); } } catch (Exception e) { throw new RuntimeException(e); } } /** * @Description: 执行一条命令 * @param connection ssh2 连接对象 * @return: ExecCmdResult 执行结果, 封装执行状态和执行结果 * @author: zongf * @time: 2019-03-25 20:47:14 */ public static ExecCmdResult execCommand(Connection connection, String command) { ExecCmdResult execCmdResult = new ExecCmdResult(); Session session = null; try { session = connection.openSession(); // 执行命令 session.execCommand(command); // 解析结果 String result = parseResult(session.getStdout()); // 若解析结果为空, 则表示执行命令发生了错误, 尝试解析错误输出 if (result.isEmpty()) { result = parseResult(session.getStderr()); }else { execCmdResult.setSuccess(true); } // 设置响应结果 execCmdResult.setResult(result); return execCmdResult; } catch (IOException e) { e.printStackTrace(); }finally { if (session != null) { session.close(); } } return null; } /** * @Description: 下载文件,只能下载文件类型, 如果是目录则抛出异常 * @param connection ssh2 连接对象 * @param remoteFilePathAbs 远程文件绝对路径名 * @param localDir 本地文件夹 * @author: zongf * @time: 2019-03-25 21:41:33 */ public static void download(Connection connection, String localDir, String... remoteFilePathAbs) { // 如果传参为空, 则返回 if(remoteFilePathAbs == null) return; SCPClient scpClient = new SCPClient(connection); try { scpClient.get(remoteFilePathAbs, localDir); } catch (IOException e) { e.printStackTrace(); } } /** * @Description: 通配符方式下载文件 * @param connection ssh2 连接对象 * @param remoteDirAbsPath 远程文件绝对路径 * @param fileNamePattern 文件名通配符匹配模式 * @param localDir 本地目录, 可接受相对绝对路径 * @author: zongf * @time: 2019-03-25 22:20:07 */ public static void downloadByPattern(Connection connection, String localDir, String remoteDirAbsPath, String fileNamePattern) { ExecCmdResult execCmdResult = execCommand(connection, "ls " + remoteDirAbsPath + "/" + fileNamePattern); if (execCmdResult.isSuccess()) { String[] files = execCmdResult.getResult().split("\n"); SCPClient scpClient = new SCPClient(connection); try { scpClient.get(files, localDir); } catch (IOException e) { e.printStackTrace(); } } } /** * @Description: 上传文件至远程服务器. 本地文件不存在时, 抛出异常,但会上传一个0字节的文件; 远程目录不存在时, 抛出异常. * @param connection ssh2 连接对象 * @param remoteDirAbsPath 远程服务器文件夹, 必须是绝对路径 * @param localFile 本地文件列表, 可接受绝对路径相对路径参数 * @author: zongf * @time: 2018-03-25 21:44:07 */ public static void upload(Connection connection, String remoteDirAbsPath, String... localFile) { // 如果传参为空, 则返回 if(localFile == null) return; SCPClient scpClient = new SCPClient(connection); try { scpClient.put(localFile, remoteDirAbsPath); } catch (IOException e) { e.printStackTrace(); } } /** * @Description: 解析命令结果 * @param inputStream 输入流 * @return: String 字符串 * @author: zongf * @time: 2019-03-25 21:06:23 */ private static String parseResult(InputStream inputStream) throws IOException { // 读取输出流内容 BufferedReader br = new BufferedReader(new InputStreamReader(inputStream, DEFAULT_CHARSET)); StringBuffer resultSb = new StringBuffer(); String line; while ((line = br.readLine()) != null) { resultSb.append(line + "\n"); } return resultSb.toString(); } } ``` ### 自定义命令返回结果 ``` /** * @Description: 命令返回结果 * @author: zongf * @date: 2019-03-25 21:03 */ public class ExecCmdResult { // 命令执行是否成功 private boolean success; // 输出结果 private String result; public boolean isSuccess() { return success; } public void setSuccess(boolean success) { this.success = success; } public String getResult() { return result; } public void setResult(String result) { this.result = result; } } ``` ## 测试类 ``` public class TestSSH2Util { private String host = "127.0.0.1"; private String username = "root"; private String password = "123456"; private Connection connection; // 执行每个单元测试用例前, 创建ssh2连接 @Before public void setup(){ connection = SSH2Util.openConnection(host, username, password); } // 执行每个单元测试后, 关闭连接 @After public void tearDown(){ connection.close(); } /** 测试连接 */ @Test public void test_connect(){ System.out.println("hostname:" + connection.getHostname()); } /** 测试执行正确命令 */ @Test public void test_exec_right() { ExecCmdResult execCmdResult = SSH2Util.execCommand(connection, "ls /home -l"); System.out.println("命令是否正确执行:" + execCmdResult.isSuccess()); System.out.println("命令执行结果:\n" + execCmdResult.getResult()); } /** 测试执行带命令通配符的命令 */ @Test public void test_exec_ms() { ExecCmdResult execCmdResult = SSH2Util.execCommand(connection, "ls -d /*bin"); System.out.println("命令是否正确执行:" + execCmdResult.isSuccess()); System.out.println("命令执行结果:\n" + execCmdResult.getResult()); } /** 测试执行错误命令 */ @Test public void test_exec_wrong() { ExecCmdResult execCmdResult = SSH2Util.execCommand(connection, "ls /2"); System.out.println("命令是否正确执行:" + execCmdResult.isSuccess()); System.out.println("命令执行结果:\n" + execCmdResult.getResult()); } /** 测试下载单个文件 */ @Test public void test_download() { SSH2Util.download(connection, ".","/etc/passwd"); } /** 测试批量下载多个文件 */ @Test public void test_download_batch(){ SSH2Util.download(connection, ".", "/etc/passwd", "/bin/bash"); } /** 测试通配符下载多个文件 */ @Test public void test_download_Parttern(){ SSH2Util.downloadByPattern(connection, ".", "/bin", "*m"); } /** 测试单个上传 */ @Test public void test_upload() { SSH2Util.upload(connection, "/tmp/zongf", "passwd"); } /** 测试批量上传 */ @Test public void test_upload_batch() { SSH2Util.upload(connection, "/tmp/zongf/tt", "rm", "udevadm"); } } ``` 最后修改:2022 年 01 月 04 日 05 : 20 PM © 转载自他站 赞赏 要多恰饭才能长胖 赞赏作者 支付宝微信