这里写目录标题
1、概述
最近项目组来了个实习生,项目经理给他安排个任务,任务大致内容是将A服务上的文件A下载到服务B上。实习生也很努力,不过被这个事情折磨了好几天才完成。甲方给了一台机器,并给了账号,密码,但没有告诉端口号,实习生看这种下载文件就直接用了SFTP,端口号用了21,结果报no such file
2、sftp和ftp的区别是什么?
实习生既然提到了用sftp,那sftp和ftp的区别是什么呢?
- ftp基于tcp来传输文件,不提供任何安全通道来在主机之间传输文件;而sftp基于ssh来加密传输文件,会提供一个安全通道,用于在主机之间传输文件。
- ftp密码和数据以纯文本格式发送;sftp以二进制的形式传递。
什么是FTP?
FTP(File Transfer Protocol,文件传输协议) 是 TCP/IP 协议组中的协议之一。
FTP协议包括两个组成部分,其一为FTP服务器,其二为FTP客户端。其中FTP服务器用来存储文件,用户可以使用FTP客户端通过FTP协议访问位于FTP服务器上的资源。
在开发网站的时候,通常利用FTP协议把网页或程序传到Web服务器上。此外,由于FTP传输效率非常高,在网络上传输大的文件时,一般也采用该协议。
什么是SFTP?
SFTP是一种安全的文件传输协议,一种通过网络传输文件的安全方法;它确保使用私有和安全的数据流来安全地传输数据。
SFTP要求客户端用户必须由服务器进行身份验证,并且数据传输必须通过安全通道(SSH)进行,即不传输明文密码或文件数据。它允许对远程文件执行各种操作,有点像远程文件系统协议。SFTP允许从暂停传输,目录列表和远程文件删除等操作中恢复。
SFTP和FTP之间的区别
SFTP和FTP非常相似,都支持批量传输(一次传输多个文件),文件夹/目录导航,文件移动,文件夹/目录创建,文件删除等。但还是存在着差异,下面我们来看看SFTP和FTP之间的区别。
1、安全通道
FTP 不提供任何安全通道来在主机之间传输文件;而SFTP协议提供了一个安全通道,用于在网络上的主机之间传输文件。
2、使用的协议
FTP使用TCP / IP协议。而,SFTP是SSH协议的一部分,它是一种远程登录信息。
3、链接方式
FTP使用TCP端口21上的控制连接建立连接。而,SFTP是在客户端和服务器之间通过SSH协议(TCP端口22)建立的安全连接来传输文件。
4、安全性
FTP密码和数据以纯文本格式发送,大多数情况下是不加密的,安全性不高。而,SFTP会在发送之前加密数据,二进制的形式传递,是无法“按原样”阅读的,安全性较高。
FTP 基于TCP来传输文件,明文传输用户信息和数据。
SFTP 基于SSH来加密传输文件,可靠性高,可断点续传。
3、问题分析
在处理问题前首先要搞清楚当前提供的账号设置与权限问题。大家可参考看下这篇文章。那肯定要关注链接方式,当时这个实习生居然用的是 21
端口。意识到问题后也改了 端口号为 22
再次访问还是不行,依然提示 no such file
。
实习生使用的代码片段:
引入jsch依赖
<dependency>
<groupId>com.jcraft</groupId>
<artifactId>jsch</artifactId>
<version>0.1.55</version> <!-- 使用适当的版本号 -->
</dependency>
具体下载逻辑
import com.jcraft.jsch.Channel;
import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.Session;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class SftpDownloadExample {
private static final Logger log = LoggerFactory.getLogger(SftpDownloadExample.class);
public void downloadFile(String user, String password, String host, int port, String remoteFile, String localDir, String localFileName) {
JSch jsch = new JSch();
Session session = null;
ChannelSftp sftpChannel = null;
try {
// 设置会话超时时间为60秒(60000毫秒)
int sessionTimeout = 60000;
// 创建会话
session = jsch.getSession(user, host, port);
session.setPassword(password);
session.setConfig("StrictHostKeyChecking", "no");
session.setTimeout(sessionTimeout);
session.connect();
// 打开 SFTP 通道
Channel channel = session.openChannel("sftp");
channel.connect();
sftpChannel = (ChannelSftp) channel;
// 下载文件
log.info("local:{}", localDir + localFileName);
sftpChannel.get(remoteFile, localDir + localFileName);
String localTempFilePath = localDir + localFileName;
log.info("sftpChannel.get() localTempFilePath:{}", localTempFilePath);
} catch (Exception e) {
log.error("Error during SFTP operation: {}", e.getMessage(), e);
throw new RuntimeException("SFTP operation failed", e);
} finally {
// 关闭 SFTP 通道
if (sftpChannel != null && sftpChannel.isConnected()) {
sftpChannel.exit();
}
// 关闭会话
if (session != null && session.isConnected()) {
session.disconnect();
}
}
}
}
上述代码解析
1、添加了错误处理来捕获下载和上传过程中可能发生的异常,并在控制台输出错误信息。
在 finally 块中,检查通道和会话是否已连接,以确保只关闭那些已成功打开的资源。
2、请注意,这个示例代码禁用了 StrictHostKeyChecking,这在生产环境中是不推荐的做法,因为它会使得中间人攻击变得更加容易。在实际应用中,你应该考虑如何安全地处理主机密钥验证。
3、超时时间的设置,这些设置可能因 JSch 版本而异,建议查阅最新的 JSch 文档以获取准确的设置方法。此外,您应该根据您的网络环境和具体需求来调整这些超时值。
此时一位老同学说了句我们是docker部署
的,那下载的远程目录是否做了映射呢?从实习生的表情看肯定是没有,下面简单说下
在使用Docker容器时,您可以使用 -p 选项来映射端口,使用 -v 选项来映射文件目录。这些选项在运行容器时(使用 docker run 命令)指定,以便您可以从宿主机访问容器的服务和文件系统。
以下是一些基本的示例:
端口映射
如果您想要将宿主机的端口映射到容器的端口,可以使用 -p 选项。例如,将宿主机的80端口映射到容器的80端口:
docker run -p 80:80 nginx
这会将宿主机的80端口映射到容器内的80端口。您还可以指定不同的宿主机和容器端口:
docker run -p 8080:80 nginx
这将把宿主机的8080端口映射到容器内的80端口。
文件目录映射
如果您想要将宿主机的文件目录映射到容器的文件系统,可以使用 -v 选项。例如,将宿主机的 /data 目录映射到容器的 /data 目录:
docker run -v /data:/data my-container
这会将宿主机的 /data 目录挂载到容器中的 /data 目录。您还可以指定只读或读写模式:
docker run -v /data:/data:ro my-container
这将挂载宿主机的 /data 目录到容器中的 /data 目录,但容器将以只读模式访问它。
同时映射端口和文件目录
您可以在同一个 docker run 命令中同时使用 -p 和 -v 选项:
docker run -p 8080:80 -v /data:/data my-container
这会将宿主机的8080端口映射到容器的80端口,并将宿主机的 /data 目录映射到容器的 /data 目录。
注意事项
确保映射的宿主机端口没有被其他服务占用。
如果您在容器中运行的是网络服务,确保它监听的是正确的端口(通常是 0.0.0.0)。
对于文件目录映射,确保宿主机上的目录存在,并且容器内的用户有适当的权限访问它。
使用端口和文件目录映射时,请考虑安全性,特别是当您公开服务或挂载敏感数据目录时。确保您的容器和网络配置符合最佳安全实践。
到了这里通过修改docker容器文件目录映射、修改了sftp请求的端口号再 发布环境后验证通过。事实证明解决问题的过程中要多考虑,多验证。