1. 概述

在现代软件开发和系统管理中,与远程服务器交互是常见需求。通过SSH客户端编程式交互服务器,可实现应用部署、配置管理、文件传输等操作。Java生态中常用的SSH客户端库包括JSchApache Mina SSHDSSHJ

本教程将演示如何使用这三个库与远程服务器交互,包括通过私钥建立连接列出指定目录的所有文件

2. 使用JSch库

JSch(Java Secure Channel)是SSH2的Java实现,提供连接SSH服务器的核心功能。

首先添加JSch依赖pom.xml

<dependency>
    <groupId>com.github.mwiede</groupId>
    <artifactId>jsch</artifactId>
    <version>0.2.18</version>
</dependency>

定义连接参数(实际使用时替换占位符):

private static final String HOST = "192.168.1.100";
private static final String USER = "admin";
private static final String PRIVATE_KEY = "/home/user/.ssh/id_rsa";
private static final int PORT = 22;
private static final String REMOTE_DIR = "/var/log";

初始化JSch并加载私钥:

JSch jsch = new JSch();
jsch.addIdentity(PRIVATE_KEY);

创建会话并连接(⚠️ 生产环境应启用主机密钥验证):

Session session = jsch.getSession(USER, HOST, PORT);
session.setConfig("StrictHostKeyChecking", "no");
session.connect();

Session对象用于创建SSH会话。为简化示例,我们禁用了严格的主机密钥检查。

接着在SSH连接上打开SFTP通道:

ChannelSftp channelSftp = (ChannelSftp) session.openChannel("sftp");
channelSftp.connect();

ChannelSftp对象支持文件上传、下载、列表等操作

2.1. 详细文件列表

通过SFTP通道获取远程目录文件列表:

Vector<ChannelSftp.LsEntry> files = channelSftp.ls(REMOTE_DIR);
for (ChannelSftp.LsEntry entry : files) {
    LOGGER.info(entry.getLongname());
}

ls()方法返回Vector<ChannelSftp.LsEntry>集合,每个元素代表文件或目录。**getLongname()返回包含权限、所有者、组、大小等详细信息的字符串**。

2.2. 仅文件名

若只需文件名,调用getFilename()方法:

Vector<ChannelSftp.LsEntry> files = channelSftp.ls(REMOTE_DIR);
for (ChannelSftp.LsEntry entry : files) {
    LOGGER.info(entry.getFilename());
}

操作完成后务必关闭连接(✅ 养成良好习惯):

channelSftp.disconnect();
session.disconnect();

3. 使用Apache Mina SSHD库

Apache Mina SSHD支持客户端和服务器端SSH协议实现。添加依赖:

<dependency>
    <groupId>org.apache.sshd</groupId>
    <artifactId>sshd-core</artifactId>
    <version>2.13.1</version>
</dependency>

<dependency>
    <groupId>org.apache.sshd</groupId>
    <artifactId>sshd-sftp</artifactId>
    <version>2.13.1</version>
</dependency>

初始化SSH客户端(使用try-with-resources自动管理资源):

try (SshClient client = SshClient.setUpDefaultClient()) {
    client.start();
    client.setServerKeyVerifier(AcceptAllServerKeyVerifier.INSTANCE);
    // ...  
}

建立SSH连接并认证:

try (ClientSession session = client.connect(USER, HOST, PORT).verify(10000).getSession()) {
    FileKeyPairProvider fileKeyPairProvider = new FileKeyPairProvider(Paths.get(privateKey));
    Iterable<KeyPair> keyPairs = fileKeyPairProvider.loadKeys(null);
    for (KeyPair keyPair : keyPairs) {
        session.addPublicKeyIdentity(keyPair);
    }

    session.auth().verify(10000);
}

FileKeyPairProvider加载私钥,由于示例私钥无密码,loadKeys()参数传null。

3.1. 详细文件列表

创建SFTP客户端并读取目录:

SftpClientFactory factory = SftpClientFactory.instance();
try (SftpClient sftp = factory.createSftpClient(session)) {
    Iterable<SftpClient.DirEntry> entriesIterable = sftp.readDir(REMOTE_DIR);
    List<SftpClient.DirEntry> entries = StreamSupport.stream(entriesIterable.spliterator(), false)
      .collect(Collectors.toList());
    for (SftpClient.DirEntry entry : entries) {
        LOGGER.info(entry.getLongFilename());
    }
}

readDir()返回Iterable<SftpClient.DirEntry>,转换为List后遍历输出详细文件名。

3.2. 仅文件名

使用getFilename()替代getLongFilename()

for (SftpClient.DirEntry entry : entries) {
    LOGGER.info(entry.getFilename());
}

4. 使用SSHJ库

SSHJ是另一个轻量级SSH客户端库。添加依赖:

<dependency>
    <groupId>com.hierynomus</groupId>
    <artifactId>sshj</artifactId>
    <version>0.38.0</version>
</dependency>

建立连接并认证(try-with-resources自动关闭):

try (SSHClient sshClient = new SSHClient()) {
    sshClient.addHostKeyVerifier(new PromiscuousVerifier());
    sshClient.connect(HOST);
    sshClient.authPublickey(USER, PRIVATE_KEY);
    // ...
}

创建SFTP客户端并列出文件:

try (SFTPClient sftpClient = sshClient.newSFTPClient()) {
    List<RemoteResourceInfo> files = sftpClient.ls(REMOTE_DIR);
    for (RemoteResourceInfo file : files) {
        LOGGER.info("Filename: " + file.getName());
    }
}

ls()返回List<RemoteResourceInfo>,通过getName()获取文件名。

获取文件详细属性:

LOGGER.info("Permissions: " + file.getAttributes().getPermissions());
LOGGER.info("Last Modification Time: " + file.getAttributes().getMtime());

getAttributes()提供权限、修改时间等元数据

5. 总结

本文演示了使用三大Java SSH库(JSch、Apache Mina SSHD、SSHJ)与远程服务器交互的核心操作:

  • ✅ 通过私钥建立安全连接
  • ✅ 列出远程目录文件(详细/精简模式)
  • ✅ 获取文件元数据

踩坑提示

  • 生产环境务必启用主机密钥验证
  • 记得关闭连接释放资源
  • 私钥文件权限需设置为600

完整示例代码见GitHub仓库


原始标题:List All Files on the Remote Server in Java | Baeldung