Spring Boot + sshd-sftp:SSH 命令与文件传输实践
在现代分布式系统中,服务器间的远程操作与文件传输是常见需求。SSH作为一种安全的网络协议,为远程登录和文件传输提供了可靠保障。
前言
在现代分布式系统中,服务器间的远程操作与文件传输是常见需求。SSH作为一种安全的网络协议,为远程登录和文件传输提供了可靠保障。
环境准备
sshd-sftp是Apache MINA项目旗下的SSH服务器组件,支持SSHv2协议,提供了丰富的API用于构建SSH客户端和服务器。相比传统的JSch库,sshd-sftp具有更活跃的社区维护和更完善的功能支持,尤其在处理大文件传输和并发连接时表现更优。
案例
效果图
图片
核心依赖
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
文件上传与下载
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); // 不存在则创建 } } }}
相关攻略
一、SSH反向连接内网主机详解 当目标主机处于防火墙或网络地址转换(NAT)设备后方时,传统的SSH直连方式往往无法奏效。此时,借助SSH反向连接技术,即可由内网主机主动向外网控制端发起连接,构建一条可靠的加密访问通道。这项技术的原理看似复杂,实际操作只需遵循清晰的“四步法”即可轻松完成。 首先,请
角色与核心任务 今天,我们来聊聊一个技术写作中常见却棘手的挑战:如何把一份充满AI腔调的冰冷文稿,打磨成一篇有血有肉、令人信服的专业文章。这并非简单的同义词替换,而是一项关于风格、温度与专业度平衡的艺术。 深度复盘:从 AI 文本到人类作品的转化路径 要达到理想的效果,背后的执行逻辑必须清晰且克制,
编辑 | 王凤枝沉寂9天之后,OpenClaw正式推送了号称里程碑的3 22大版本更新,但我们给普通用户的核心建议是,千万别急着点升级。3月22日,项目创始人彼得·斯坦伯格(Peter Steinb
新智元报道编辑:Aeneas【新智元导读】一夜爆红的ClawdBot,正在把无数公司和个人推向深渊:端口裸奔、无鉴权、可被远程接管。现在,暴力破解、数据清空已经真实发生了,这不是危言耸听。各位CEO
在现代分布式系统中,服务器间的远程操作与文件传输是常见需求。SSH作为一种安全的网络协议,为远程登录和文件传输提供了可靠保障。 前言在现代分布式系统中,服务器间的远程操作与文件传输是常见需求。SSH
热门专题
热门推荐
公安部就电子数据取证规则公开征求意见,拟将网络安全等行政案件纳入适用范围,并规范取证流程与核心概念。新规特别明确了获取密码、调取通讯内容等特殊程序,需经严格审批并保障当事人权利。配套法律文书也同步优化,以构建更规范且注重权利保障的取证体系。
理想L9和LIvis的定价策略刚掀起波澜,小鹏GX的最终价格就给出了更猛烈的回应——从近40万元的预售价直降至27万元起。用小鹏产品矩阵负责人吴安飞的话说,这叫“9系的产品,8系的价格”。 这12万元的下调,效果堪称立竿见影。发布会次日,小鹏集团港股股价一度大涨超8%。更关键的是市场订单:上市12小
5月21日,环塔拉力赛新疆且末赛段大营迎来了一位备受瞩目的访客——知名零售企业胖东来的创始人于东来。他专程前往长城汽车车队营地,与参赛车手及后勤团队进行了深度交流。据悉,于东来此次自驾越野之旅已历时一月,随行车队中包含多款国产越野车型。经过实地驾驶与多维度对比,他对以长城汽车为代表的国产越野车品质给
比特币官方入口在哪里?一个核心门户的权威指南 说起比特币,很多人第一反应是去找它的“官网”或“官方App”。但这里有个关键点需要先理清:比特币本质上是一种去中心化的全球数字货币,它不属于任何一家公司或机构,而是由一个庞大的、遍布全球的社区共同维护。因此,它并没有传统意义上由某个企业运营的“官方网站”
Ring-2 5-1T是什么 在当今大模型技术激烈竞争的赛道上,追求更长的上下文处理能力和更强大的深度推理性能已成为核心焦点。近日,蚂蚁集团旗下的inclusionAI团队重磅开源了Ring-2 5-1T模型,这是一个参数规模高达万亿级别的混合线性思考大语言模型。该模型基于先进的Ling 2 5架构





