用 Java 列出遠端伺服器上的所有文件
1. 概述
與遠端伺服器互動是現代軟體開發和系統管理中的常見任務。使用 SSH 用戶端與遠端伺服器進行程式設計交互,可以部署應用程式、管理配置、傳輸檔案等。 JSch、Apache Mina SSHD 和 SSHJ 函式庫是 Java 中流行的 SSH 用戶端。
在本教程中,我們將學習如何使用 JSch、Apache Mina SSHD 和 SSHJ 庫與遠端伺服器互動。此外,我們還將了解如何使用私鑰建立與遠端伺服器的連接,並列出伺服器中特定目錄中的所有資料夾。
2. 使用 JSch 函式庫
JSch(Java 安全通道)庫提供了用於建立與 SSH 伺服器的連線的類別。它是 SSH2 的 Java 實作。
首先,我們將JSch 依賴項加入pom.xml
中:
<dependency>
<groupId>com.github.mwiede</groupId>
<artifactId>jsch</artifactId>
<version>0.2.18</version>
</dependency>
接下來,讓我們定義連接詳細資訊以建立與遠端伺服器的連接:
private static final String HOST = "HOST_NAME";
private static final String USER = "USERNAME";
private static final String PRIVATE_KEY = "PRIVATE_KEY";
private static final int PORT = 22;
private static final String REMOTE_DIR = "REMOTE_DIR";
在這裡,我們定義主機、使用者和身份驗證金鑰的路徑。此外,我們還定義了要列出其資料夾的連接埠和遠端目錄。
接下來,讓我們建立一個JSch
物件並新增用於身份驗證的PRIVATE_KEY
:
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());
}
在上面的程式碼中,我們在ChannelSftp
物件上呼叫ls()
方法,該方法傳回ChannelSftp.LsEntry
物件的Vector
,每個物件代表一個檔案或目錄。然後,我們循環遍歷文件和目錄列表並記錄每個文件或目錄的長名稱。 getLongname()
方法包括其他詳細信息,例如權限、所有者、群組和大小。
2.2.僅檔案名稱
如果我們只對檔案名稱感興趣,我們可以呼叫ChannelSftp.LsEntry
物件上的getFilename()
方法:
Vector<ChannelSftp.LsEntry> files = channelSftp.ls(REMOTE_DIR);
for (ChannelSftp.LsEntry entry : files) {
LOGGER.info(entry.getFilename());
}
值得注意的是,操作成功後我們必須關閉SSH會話和SFTP頻道:
channelSftp.disconnect();
session.disconnect();
從本質上講,關閉連線有助於釋放資源。
3. 使用 Apache Mina SSHD 函式庫
Apache Mina SSHD 程式庫旨在支援旨在為客戶端和伺服器端提供 SSH 協定的 Java 應用程式。
我們可以執行多種 SSH 操作[sshd-core](https://mvnrepository.com/artifact/org.apache.sshd/sshd-core)
例如檔案傳輸、部署等。
<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 (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
物件來載入私有金鑰,並且由於我們的私有金鑰不需要密碼短語,因此我們將 null 傳遞給loadKeys()
方法。
3.1.詳細文件列表
要列出遠端伺服器上的資料夾,讓我們建立一個SftpClientFactory
物件以透過已建立的 SSH 會話開啟 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());
}
}
在這裡,我們讀取遠端目錄並取得目錄條目的Iterable
,並將其轉換為List
。然後我們將長檔名記錄到控制台。由於我們使用了 try-with-resources 區塊,因此我們不需要明確關閉會話。
3.2.僅檔案名稱
但是,為了只取得檔案名,我們可以在目錄條目上使用getFilename()
方法,而不是getLongFileName()
:
for (SftpClient.DirEntry entry : entries) {
LOGGER.info(entry.getFilename());
}
getFilename()
消除其他檔案資訊並僅記錄檔案名稱。
4.使用SSHJ函式庫
SSHJ 庫也是一個 Java 庫,它提供用於連接遠端伺服器並與遠端伺服器互動的類別。要使用該庫,我們將其依賴項新增至pom.xml
:
<dependency>
<groupId>com.hierynomus</groupId>
<artifactId>sshj</artifactId>
<version>0.38.0</version>
</dependency>
另外,讓我們維護前面部分中使用的連接詳細資訊。
讓我們建立一個SSHClient
物件來建立與遠端伺服器的連線:
try (SSHClient sshClient = new SSHClient()) {
sshClient.addHostKeyVerifier(new PromiscuousVerifier());
sshClient.connect(HOST);
sshClient.authPublickey(USER, PRIVATE_KEY);
// ...
}
然後,讓我們在已建立的 SSH 會話上建立 SFTP 通道:
try (SFTPClient sftpClient = sshClient.newSFTPClient()) {
List<RemoteResourceInfo> files = sftpClient.ls(REMOTE_DIR);
for (RemoteResourceInfo file : files) {
LOGGER.info("Filename: " + file.getName());
}
}
在上面的程式碼中,我們呼叫ls()
來接受sftpClient
上的遠端目錄並將其儲存為RemoteResourseInfo
類型。然後我們循環遍歷文件條目並將文件名記錄到控制台。
最後,我們可以使用getAttributes()
方法來取得更多關於文件的詳細資訊:
LOGGER.info("Permissions: " + file.getAttributes().getPermissions());
LOGGER.info("Last Modification Time: " + file.getAttributes().getMtime());
在這裡,我們透過呼叫getAttributes()
方法上的getPermissions()
和getMtime()
方法進一步記錄檔案權限和修改時間。
5. 結論
在本文中,我們學習如何使用 JSch、Apache SSHD Mina 和 SSHJ 函式庫與遠端伺服器互動。此外,我們還了解如何建立安全連線、使用私鑰進行身份驗證以及執行基本文件操作。
與往常一樣,範例的完整原始程式碼可在 GitHub 上取得。