Java实现远程文件复制(基于SCP命令)

本文介绍了SCP命令的工作原理,提供从本地到远程及从远程到本地的复制示例,并指导如何使用Java结合JSch库在Java应用中实现SSH安全文件复制,包括环境配置和代码实现步骤。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在这里插入图片描述

本文主要介绍SCP命令以及如何使用Java在不同的远程服务器之间使用SCP命令(安全复制协议)复制文件/文件夹。

什么是SCP命令

SCP是Secure Copy的简写,用于在Linux下进行远程拷贝文件的命令。它的主要优点是可以在不泄露敏感信息的情况下在远程服务器计算机之间传输文件。因为是基于SSH协议的,所以具有很强的安全性。

1. SCP命令的基本语法

SCP命令的基本语法如下:

scp [参数] [源文件] [目标路径]

其中:

  • 参数:可以是一些选项,例如-r表示层级复制文件夹。
  • 源文件:要复制的文件或文件夹的路径。
  • 目标路径:文件复制到的目标路径,可以是远程服务器的路径,格式为[用户名]@[远程服务器IP]:[目标路径]

参数说明:

  • -1: 强制scp命令使用协议ssh1
  • -2: 强制scp命令使用协议ssh2
  • -4: 强制scp命令只使用IPv4寻址
  • -6: 强制scp命令只使用IPv6寻址
  • -B: 使用批处理模式(传输过程中不询问传输口令或短语)
  • -C: 允许压缩。(将-C标志传递给ssh,从而打开压缩功能)
  • -p:保留原文件的修改时间,访问时间和访问权限。
  • -q: 不显示传输进度条。
  • -r: 递归复制整个目录。
  • -v:详细方式显示输出。scp和ssh(1)会显示出整个过程的调试信息。这些信息用于调试连接,验证和配置问题。
  • -c cipher: 以cipher将数据传输进行加密,这个选项将直接传递给ssh。
  • -F ssh_config: 指定一个替代的ssh配置文件,此参数直接传递给ssh。
  • -i identity_file: 从指定文件中读取传输时使用的密钥文件,此参数直接传递给ssh。
  • -l limit: 限定用户所能使用的带宽,以Kbit/s为单位。
  • -o ssh_option: 如果习惯于使用ssh_config(5)中的参数传递方式。
  • -P port:注意是大写的P, port是指定数据传输用到的端口号。
  • -S program: 指定加密传输时所使用的程序。此程序必须能够理解ssh(1)的选项。

2. 从本地复制到远程

在本地服务器上将/opt/files目录下所有的文件传输到服务器192.168.158.128的/opt目录下,命令为:

scp -r /opt/files root@192.168.158.128:/opt/

3. 从远程复制到本地

在本地服务器上操作,将服务器192.168.158.128上/opt目录下所有的文件全部复制到本地的/opt/files目录下,命令为:

scp -r root@192.168.158.128:/opt /opt/files/

Java实现远程文件复制

步骤1:准备环境

确保开发环境中安装了以下工具和库:

  • Java开发环境
  • JSch库:用于连接和执行SCP命令
<!-- jcraft JSch -->
<dependency>
    <groupId>com.jcraft</groupId>
    <artifactId>jsch</artifactId>
    <version>0.1.53</version>
</dependency>

因为命令执行的原因,需要确保服务器已经安装sshpass,主要用于自动化SSH密码输入

yum install sshpass

步骤2:创建代码

使用以下代码来实现远程文件复制功能:

/**
 * 远程复制文件工具类
 */
public class RemoteScpUtils {

    /**
     * 远程复制文件
     *
     * @param sourcePath                源文件路径
     * @param destinationPath           目标文件路径
     * @param sourceRemoteUsername      源远程用户名
     * @param sourceRemotePassword      源远程用户密码
     * @param sourceRemoteIp            源远程地址IP
     * @param destinationRemoteUsername 目标远程用户名
     * @param destinationRemotePassword 目标远程用户密码
     * @param destinationRemoteIp       目标远程地址IP
     * @throws JSchException 异常信息
     */
    public static void scpFileCommand(String sourcePath, String destinationPath, String sourceRemoteUsername, String sourceRemotePassword, String sourceRemoteIp, String destinationRemoteUsername, String destinationRemotePassword, String destinationRemoteIp) throws JSchException {
        JSch jsch = new JSch();
        Session session = null;
        Channel channel = null;

        try {
            // 创建SSH会话
            session = jsch.getSession(sourceRemoteUsername, sourceRemoteIp);
            session.setConfig("StrictHostKeyChecking", "no");
            session.setPassword(sourceRemotePassword);
            session.connect();

            // 打开SCP通道
            channel = session.openChannel("exec");

            // 构建SCP命令
            List<String> commandList = new ArrayList<>();
            commandList.add("sshpass -p " + destinationRemotePassword); // 跳过密码输入
            commandList.add("scp -r");      // 添加 scp 命令
            commandList.add(sourcePath);    // 添加源文件路径
            // 添加目标文件路径, 包括用户名和IP地址
            commandList.add(destinationRemoteUsername + "@" + destinationRemoteIp + ":" + destinationPath);
            String command = String.join(" ", commandList);

            // 设置命令
            ((ChannelExec) channel).setCommand(command);

            // 连接通道
            channel.connect();
        } finally {
            // 关闭通道
            if (channel != null && channel.isConnected()) channel.disconnect();
            // 关闭会话
            if (session != null && session.isConnected()) session.disconnect();
            System.out.println(":::::::::::::::::::::::: 远程复制文件成功 :::::::::::::::::::::");
        }
    }

}

测试代码:

@Test
public void scpTest() {

        String sourcePath = "/opt/files";               // 源文件路径
        String destinationPath = "/opt/";               // 目标文件路径
        String sourceRemoteUsername = "root";           // 远程服务器用户名
        String sourceRemotePassword = "root";           // 远程服务器密码
        String sourceRemoteIp = "192.168.xx.xx";        // 远程服务器IP
        String destinationRemoteUsername = "root";      // 远程服务器用户名
        String destinationRemotePassword = "root";      // 远程服务器密码
        String destinationRemoteIp = "192.168.xx.xx";   // 远程服务器IP

        try {
            // SCP复制文件
            // 将源服务器的 /opt/files 复制到目标服务器的 /opt 目录下
            RemoteScpUtils.scpFileCommand(
                    sourcePath,
                    destinationPath,
                    sourceRemoteUsername,
                    sourceRemotePassword,
                    sourceRemoteIp,
                    destinationRemoteUsername,
                    destinationRemotePassword,
                    destinationRemoteIp
            );
        } catch (JSchException e) {
            throw new RuntimeException(e);
        }

}

步骤3:运行代码

编译并运行上面的Java代码,将会连接到远程服务器并复制文件。如果没有复制成功需要检查一下环境尤其是sshpass有没有安装。

结论

通过这个简单的案例,就可以使用Java和SCP命令来创建一个远程文件复制工具。可以帮助在不同的远程服务器之间传输文件。

在这里插入图片描述

Java文件复制(远程复制(网络传输),用于远程备份文件)(支持文件夹,嵌套子文件) import java.io.*; import java.util.*; public class FileSelection { private File rootDirectory;//根目录 private File[] fileList;//文件目录下面的文件列表(包括目录,用于多次判断) private ArrayList fileArrayList; // 用于存储文件(只是文件)列表 //初始化参数 public FileSelection() { fileArrayList=new ArrayList(); rootDirectory = new File("Test"); rootDirectory.mkdir(); } //获得文件(不包括目录)的列表 public void initFileArrayList() { if (rootDirectory.isDirectory()) { //遍历目录下面的文件和子目录 fileList = rootDirectory.listFiles(); for (int i = 0; i < fileList.length; i++) { //如果是文件,添加到文件列表中 if(fileList[i].isFile()){ fileArrayList.add(fileList[i]); } //否则递归遍历子目录 else if (fileList[i].isDirectory()) { fileList[i].mkdir(); rootDirectory=fileList[i]; initFileArrayList(); } } } } //将文件信息添加到列表中 public void addFiles(File f){ fileArrayList.add(f); } //访问器返回文件列表 public ArrayList getFileArrayList() { return fileArrayList; } } -------------------- BackupClient.java package com.xinxin.Client; import java.io.*; import java.net.*; /** * * @author Administrator *@version 1.0 *BackupClient类实现文件的传输到服务器 */ public class BackupClient implements Runnable{ private int port;//服务器端口 private InetAddress ipAddress;//服务器IP地址 private Socket clientSocket;//客户端套接字 private InputStream inputStream;//网络输入流 private OutputStream outputStream;//网络输出流 private File file; //构造函数(获得服务器端IP地址和监听端口号) public BackupClient(InetAddress ipAddress,int port,File file){ this.ipAddress=ipAddress; this.port=port;
java里可以通过Ganymed SSH-2, Expect4j等实现ssh登录,由于Ganymed SSH-2是纯java实现,并且可以实现scp,sftp等,因此我们采用Ganymed SSH-2 1> 下载安装 从http://code.google.com/p/ganymed-ssh-2/ 下载,我们用的是ganymed-ssh2-build251beta1.zip。 在eclipse里新建一个测试工程,并将解压后的ganymed-ssh2-build251beta1.jar拷到工程的lib目录下,然后在工程属性的java build path里添加这个jar的library。 2> ssh 将解压后的examples目录下的Basic.java 拷到工程的src目录,编译运行以后可以在控制台看到输出结果。除了执行一条命令,也可以执行一个shell脚本。 例如将Basic.java中的“uname -a && date && uptime && who” 改为“/home/lss/test.sh”, test.sh的内容如下: #! /bin/sh echo "testing shell"; ls; 在eclipse里运行以后的结果为: Here is some information about the remote host: testing shell 1 test.sh ExitCode: 0 需要注意的是在一个session里只能执行一次命令,因此如果想在server上执行多个命令,要么打开多个session,要么在一个session里去执行一个shell脚本,shell脚本里去执行多个命令。 每次执行完以后,如果正确将返回ExitCode: 0,因此程序里可以通过sess.getExitStatus()来判断命令是否被正确执行。 3> scp 首先在程序里import ch.ethz.ssh2.SCPClient; 然后通过下面的方法来实现SCPClient scpClient = conn.createSCPClient(); scpClient.put("localFiles", "remoteDirectory"); //从本地复制文件远程目录 scpClient.get("remoteFiles","localDirectory"); //从远程获取文件 例如: scpClient.put("D:\\localTest.txt", "/home/bill/"); 需要注意的是windows的本地目录要用双斜杠来分隔目录。 scpClient.put("/home/bill/remoteTest.txt", "D:\\"); 4> sftp 首先在程序里import ch.ethz.ssh2.SFTPv3Client; SFTPv3Client sftpClient = new SFTPv3Client(conn); sftpClient.mkdir("newRemoteDir", 0755); //远程新建目录 ,第二个参数是创建的文件夹的读写权限 sftpClient.rmdir("oldRemoteDir"); //远程删除目录 另外还有创建删除文件,读写文件等接口,参见http://www.ganymed.ethz.ch/ssh2/javadoc/ch/ethz/ssh2/SFTPv3Client.html
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

霁晨晨晨

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值