游乐游手机版
首页/科技数码/文章详情

Spring Boot + sshd-sftp:SSH 命令与文件传输实践

时间:2025-12-15 21:35
在现代分布式系统中,服务器间的远程操作与文件传输是常见需求。SSH作为一种安全的网络协议,为远程登录和文件传输提供了可靠保障。 前言在现代分布式系统中,服务器间的远程操作与文件传输是常见需求。SSH

在现代分布式系统中,服务器间的远程操作与文件传输是常见需求。SSH作为一种安全的网络协议,为远程登录和文件传输提供了可靠保障。

前言

在现代分布式系统中,服务器间的远程操作与文件传输是常见需求。SSH作为一种安全的网络协议,为远程登录和文件传输提供了可靠保障。

环境准备

sshd-sftp是Apache MINA项目旗下的SSH服务器组件,支持SSHv2协议,提供了丰富的API用于构建SSH客户端和服务器。相比传统的JSch库,sshd-sftp具有更活跃的社区维护和更完善的功能支持,尤其在处理大文件传输和并发连接时表现更优。

案例

效果图

图片图片

核心依赖

org.apache.sshd sshd-sftp 2.10.0

SSH 连接管理

建立和管理SSH连接是所有操作的基础,合理的连接池设计能有效提升系统性能。

创建SshClientUtil工具类管理连接生命周期:

import lombok.extern.slf4j.Slf4j;import org.apache.sshd.client.SshClient;import org.apache.sshd.client.session.ClientSession;import org.springframework.beans.factory.annotation.Value;import org.springframework.stereotype.Component;import java.io.IOException;@Slf4j@Componentpublic class SshClientUtil { @Value("${ssh.host:182.168.1.101}") private String host; @Value("${ssh.port:22}") private int port; @Value("${ssh.username:root}") private String username; @Value("${ssh.password:root}") private String password; @Value("${ssh.timeout:5000}") private int timeout; private SshClient client; private ClientSession session; /** * 建立SSH连接 */ public void connect() throws IOException { if (session != null && session.isOpen()) { return; } client = SshClient.setUpDefaultClient(); client.start(); session = client.connect(username, host, port) .verify(timeout) .getSession(); session.addPasswordIdentity(password); session.auth().verify(timeout); log.info("SSH连接成功"); } /** * 断开SSH连接 */ public void disconnect() throws IOException { if (session != null && session.isOpen()) { session.close(); } if (client != null && client.isStarted()) { client.stop(); } } public ClientSession getSession() throws IOException { if (session == null || session.isEmpty() ||session.isClosed()) { connect(); } return session; }}

远程命令执行

通过SSH协议执行远程命令是服务器管理的常用功能,需要处理命令输出和错误信息。

import org.apache.sshd.client.channel.ChannelExec;import org.apache.sshd.client.channel.ClientChannelEvent;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.beans.factory.annotation.Value;import org.springframework.stereotype.Service;import java.io.*;import java.util.ArrayList;import java.util.Arrays;import java.util.List;@Servicepublic class RemoteCommandService { @Autowired private SshClientUtil sshClientUtil; @Value("${ssh.charset:UTF-8}") private String charset; /** * 执行单条SSH命令 * * @param command 命令字符串 * @return 命令输出结果 */ public String executeCommand(String command) throws IOException { try (ChannelExec channel = sshClientUtil.getSession().createExecChannel(command)) { ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); ByteArrayOutputStream errorStream = new ByteArrayOutputStream(); channel.setOut(outputStream); channel.setErr(errorStream); channel.open(); channel.waitFor(Arrays.asList(ClientChannelEvent.CLOSED), 0); int exitStatus = channel.getExitStatus(); if (exitStatus != 0) { String errorMsg = new String(errorStream.toByteArray(), charset); throw new RuntimeException("命令执行失败: " + errorMsg); } return new String(outputStream.toByteArray(), charset); } } /** * 执行多条命令(按顺序执行) * * @param commands 命令列表 * @return 命令输出结果列表 */ public List executeCommands(List commands) throws IOException { List results = new ArrayList<>(); for (String cmd : commands) { results.add(executeCommand(cmd)); } return results; }}

文件上传与下载

SFTP是基于SSH的安全文件传输协议,相比FTP具有更高的安全性。

import org.apache.sshd.sftp.client.SftpClient;import org.apache.sshd.sftp.client.SftpClientFactory;import org.apache.sshd.sftp.common.SftpException;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.beans.factory.annotation.Value;import org.springframework.stereotype.Service;import java.io.*;import java.nio.file.Files;import java.nio.file.Path;import java.nio.file.Paths;import java.util.ArrayList;import java.util.Arrays;import java.util.List;@Servicepublic class SftpFileService { @Autowired private SshClientUtil sshClientUtil; @Value("${ssh.charset:UTF-8}") private String charset; /** * 上传本地文件到远程服务器 * * @param localFilePath 本地文件路径 * @param remoteDir 远程目录路径 */ public void uploadFile(String localFilePath, String remoteDir) throws IOException { try (SftpClient client = SftpClientFactory.instance().createSftpClient(sshClientUtil.getSession()); SftpClient.CloseableHandle handle = client.open(remoteDir, SftpClient.OpenMode.Write, SftpClient.OpenMode.Create)) { // 上传文件 Path local = Paths.get(localFilePath); client.write(handle, 0, Files.readAllBytes(local)); } } /** * 从远程服务器下载文件 * * @param remoteFilePath 远程文件路径 * @param localDir 本地目录路径 */ public void downloadFile(String remoteFilePath, String localDir) throws IOException { try (SftpClient client = SftpClientFactory.instance().createSftpClient(sshClientUtil.getSession()); SftpClient.CloseableHandle handle = client.open(remoteFilePath, SftpClient.OpenMode.Read); OutputStream out = Files.newOutputStream(Paths.get(localDir))) { long size = client.stat(handle).getSize(); byte[] buffer = new byte[8192]; for (long offset = 0; offset < size; ) { int len = client.read(handle, offset, buffer, 0, buffer.length); out.write(buffer, 0, len); offset += len; } } } /** * 递归创建远程目录 */ private void mkdirs(SftpClient client, String dir) throws IOException { String[] dirs = dir.split("/"); String currentDir = ""; for (String d : dirs) { if (d.isEmpty()) continue; currentDir += "/" + d; try { client.stat(currentDir); // 检查目录是否存在 } catch (IOException e) { client.mkdir(currentDir); // 不存在则创建 } } }}

来源:https://www.51cto.com/article/824502.html
上一篇四海兄弟:故乡PS5销量领先,总销120万份反映平台差异 下一篇二手车选购七大要点:避坑指南
本站内容用于信息整理与展示,如有侵权或内容问题请及时联系处理。

相关推荐

补充同频道和同主题内容,方便继续浏览更多相关内容。

同类最新

继续查看同栏目最近更新的文章。

更多
国内首个开源鸿蒙机器人系统社区启动,破局国产软件生态
科技数码 · 2026-07-01

国内首个开源鸿蒙机器人系统社区启动,破局国产软件生态

6月30日,机器人ETF易方达(159530)盘中涨幅超过4 3%,报收1 555元,机器人板块整体表现活跃。消息面上,国内首个基于开源鸿蒙的机器人操作系统社区(M-Robots)正式启动运营并发布了年度发展路线,日本GMO INTERNET集团子公司与宇树科技达成合作协议。国产机器人软件生态建设取

ROI利剑悬顶,AI员工面临效益大考
科技数码 · 2026-07-01

ROI利剑悬顶,AI员工面临效益大考

先说说现在AI行业一个普遍现象:几乎所有公司都在按“使用量”来收费。不管是按token消耗算,还是按额度制走,本质上都是“用多少,付多少”。 这套模式放在模型API上当然没问题,但放到那些越来越深入企业工作流的Agent身上,就有点水土不服了。你想想,一个Agent为了完成一个任务,需要反复读取上下

武汉光谷三年投入超10亿元打造智能体之城
科技数码 · 2026-07-01

武汉光谷三年投入超10亿元打造智能体之城

6月29日,武汉光谷智能体经济大会正式召开,会上重磅发布了“光谷智能体引力计划”。根据规划,未来3年内,光谷将在政策扶持、算力基建、产业基金等领域投入超过10亿元,致力于全域打造智能体之城,抢占人工智能产业新高地。 具体如何推进?主要依托湖北科创供应链平台,设立光谷智能体场景发布厅,引导百亿级人工智

苹果印度梦受挫 iPhone 18 Pro机密文件泄露
科技数码 · 2026-07-01

苹果印度梦受挫 iPhone 18 Pro机密文件泄露

从暗网流出的文件来看,窃取苹果印度供应商塔塔电子数据的勒索软件组织,此次曝光的“重磅信息”中,明确包含了即将发布的iPhone 18 Pro机型的敏感组件清单、供应商名单以及实物照片。消息人士和文件内容均证实了这一点。 这绝非小事。苹果在全球供应商之间精密运转的iPhone组装业务,直接面临威胁。众

企业级AI聚焦全场景闭环办事加速成为业绩抓手
科技数码 · 2026-07-01

企业级AI聚焦全场景闭环办事加速成为业绩抓手

AI产业正从技术验证阶段迈向深度产业落地的关键转型期,这一趋势正成为驱动企业数智化增长的核心引擎。6月30日,联想乐享迎来重要升级——4 0版本正式发布。作为业界首个企业级超级智能体,此次升级带来了三项扎实成果:自主研制的Harness运行层、自我进化与反思机制,以及多场景Skill能力体系,三大支