背景说明
涉及通过程序进行机器间的文件Copy的场景,我们一般会使用ssh连接机器,通过scp命令进行文件copy。
此种方案的前提是:机器间事先要配置免密码互通。
但是,如果客户现场机器数量过多,配置免密操作比较麻烦;或者处于安全考虑,客户不允许机器之间免密访问。
此时,需要另辟蹊径,找其他方案实现。
需求场景:提供机器的IP,登录用户名、登录密码,但是不配置机器间的免密登录,实现机器之间的文件传输。
Java 实现
1、工具类
ScpUtil.java
package com.miracle.luna.scp; import org.apache.sshd.client.SshClient; import org.apache.sshd.client.session.ClientSession; import org.apache.sshd.scp.client.ScpClient; import org.apache.sshd.scp.client.ScpClientCreator; /** * @author Miracle Luna * @date 2021/7/19 */ public class ScpUtil { // private static String host = "192.168.67.48"; private static String host = "192.168.67.39"; // private static String host = "192.168.71.29"; private static String username = "root"; private static String password = "password"; private static Integer port = 22; // private static String local = "F:\\miracle\\*"; private static String local = "/home/miracle/*"; private static String remote = "/home/samba/"; // private static String remote = "F:\\luna\\"; public static void scpFile(String local, String remote) throws Exception { long startTime = System.currentTimeMillis(); // 创建 SSH客户端 SshClient client = SshClient.setUpDefaultClient(); // 启动 SSH客户端 client.start(); // 通过主机IP、端口和用户名,连接主机,获取Session ClientSession session = client.connect(username, host, port).verify().getSession(); // 给Session添加密码 session.addPasswordIdentity(password); // 校验用户名和密码的有效性 boolean isSuccess = session.auth().verify().isSuccess(); // 认证成功 if (isSuccess) { long middleTime = System.currentTimeMillis(); System.out.println("Connect host cost time: " + (middleTime - startTime) / 1000.0 + "s."); ScpClientCreator creator = ScpClientCreator.instance(); // 创建 SCP 客户端 ScpClient scpClient = creator.createScpClient(session); System.out.println("Scp beginning."); // ScpClient.Option.Recursive:递归copy,可以将子文件夹和子文件遍历copy scpClient.upload(local, remote, ScpClient.Option.Recursive); System.out.println("Scp finished."); // 释放 SCP客户端 if (scpClient != null) { scpClient = null; } // 关闭 Session if (session != null && session.isOpen()) { session.close(); } // 关闭 SSH客户端 if (client != null && client.isOpen()) { client.stop(); client.close(); } } long endTime = System.currentTimeMillis(); System.out.println("Total Cost time: " + (endTime - startTime) / 1000.0 + "s."); } public static void main(String[] args) throws Exception { scpFile(local, remote); } }
2、运行结果
Connect host cost time: 6.519s. Scp beginning. Scp finished. Total Cost time: 9.569s.
3、Maven依赖
<!-- https://mvnrepository.com/artifact/org.apache.sshd/sshd-common --> <dependency> <groupId>org.apache.sshd</groupId> <artifactId>sshd-common</artifactId> <version>2.7.0</version> </dependency> <!-- https://mvnrepository.com/artifact/org.apache.sshd/sshd-core --> <dependency> <groupId>org.apache.sshd</groupId> <artifactId>sshd-core</artifactId> <version>2.7.0</version> </dependency> <!-- https://mvnrepository.com/artifact/org.apache.sshd/sshd-scp --> <dependency> <groupId>org.apache.sshd</groupId> <artifactId>sshd-scp</artifactId> <version>2.7.0</version> </dependency>
补充说明
该方式适用于Linux到Linux、Linux到Windows、Windows到Linux、Windows到Windows系统间的文件拷贝。
(如果和Windows操作系统文件交互,前提是:Windows安装了SSH服务端,如OpenSSH,FreeSSHd,Bitvise SSH Server等)