Sftp 文件上传无法与 Docker 容器中的 Apache MINA SSHD 和 JIMFS 一起使用
我正在处理一个棘手的问题:
出于测试目的,我使用 Apache Mina SSHD 和 JIMFS 来模拟远程 sftp 服务器 - 仅在本地和测试环境中。从未投入生产。
在我的 Spring Boot 应用程序中,我在应用程序启动期间启动 Apache Mina sshd。我使用 jimfs(尝试过 unix 和 osX)为 FileSystemFactory 创建了一个虚拟文件系统。 我的业务代码在生产环境中调用远程 sftp 服务器,而在测试环境中,它会调用本地主机上的 mina sshd 服务器。 它除了将文件上传到 sftp 服务器之外什么也不做。
这在我的本地机器上运行得很好,但是当我在测试环境(docker 容器)中运行它时,我收到“文件或目录未找到”错误消息。
com.jcraft.jsch.SftpException: No such file or directory
at com.jcraft.jsch.ChannelSftp.throwStatusError(ChannelSftp.java:2873)
at com.jcraft.jsch.ChannelSftp._put(ChannelSftp.java:594)
at com.jcraft.jsch.ChannelSftp.put(ChannelSftp.java:475)
at com.jcraft.jsch.ChannelSftp.put(ChannelSftp.java:365)
at our.service.core.client.sftp.SftpClient.upload(SftpClient.java:89)
在应用程序启动期间创建 JIMFS 文件系统:
public class MockSftpServerInitializer implements ApplicationListener<ApplicationReadyEvent> {
@Override
public void onApplicationEvent(ApplicationReadyEvent event) {
SshServer sshd = SshServer.setUpDefaultServer();
sshd.setHost("localhost");
sshd.setPort(1234);
sshd.setCommandFactory(new ScpCommandFactory());
sshd.setKeyPairProvider(new SimpleGeneratorHostKeyProvider(new File("host-key.ser")));
sshd.setPublickeyAuthenticator(getPublickeyAuthenticator());
sshd.setFileSystemFactory(getInMemoryFileSystemFactory());
List<NamedFactory<Command>> sftpCommandFactory = new ArrayList<>();
sftpCommandFactory.add(new SftpSubsystemFactory());
sshd.setSubsystemFactories(sftpCommandFactory);
try {
sshd.start();
} catch (Exception e) {
throw new RuntimeException("Unable to start sshd", e);
}
}
private FileSystemFactory getInMemoryFileSystemFactory() {
return session -> getInMemoryFileSystem();
}
private FileSystem getInMemoryFileSystem() {
return Jimfs.newFileSystem(
Configuration.osX()
.toBuilder()
.setWorkingDirectory("/")
.setMaxSize(1024*1024*4)
.setDefaultAttributeValue("posix:permissions", "rwxrw-rw-")
.setAttributeViews("basic", "owner", "posix", "unix", "acl", "user")
.build());
}
}
文件上传:
public class SftpClient {
public boolean upload(String source, String destination) {
Session session = null;
ChannelSftp sftpChannel = null;
try {
sftpProvider.addIdentity("Identity", privateKey.getBytes(), publicKey.getBytes(), null);
session = sftpProvider.getSession(username, host, port);
session.setConfig("StrictHostKeyChecking", "no");
session.connect();
Channel channel = session.openChannel("sftp");
channel.connect();
sftpChannel = (ChannelSftp) channel;
sftpChannel.put(source, destination);
log.info("Successful upload of file {} to SFTP server {}.", source, host);
return true;
} catch (SftpException | JSchException ex) {
log.error("Failed upload of file {} to SFTP server {}.", source, host);
log.error("{}", ex);
return false;
} finally {
if (sftpChannel != null) {
sftpChannel.disconnect();
}
if (session != null) {
session.disconnect();
}
}
}
}
我很感激任何关于为什么它在本地工作但在我们的 docker 容器中工作的提示。
I'm dealing with a tough one:
For testing purposes I use Apache Mina SSHD and JIMFS to mock a remote sftp server - only locally and in test environment. Never in production.
In my Spring Boot application I start a Apache Mina sshd during application startup. I create a virtual filesystem with jimfs (tried unix and osX) for the FileSystemFactory
.
My business code calls a remote sftp server in production and in test environment it calls the mina sshd server on localhost instead.
It does nothing else than uploading a file to the sftp server.
This works very well on my machine locally but i get a "file or directory not found" error message when I run this in our test environment (a docker container).
com.jcraft.jsch.SftpException: No such file or directory
at com.jcraft.jsch.ChannelSftp.throwStatusError(ChannelSftp.java:2873)
at com.jcraft.jsch.ChannelSftp._put(ChannelSftp.java:594)
at com.jcraft.jsch.ChannelSftp.put(ChannelSftp.java:475)
at com.jcraft.jsch.ChannelSftp.put(ChannelSftp.java:365)
at our.service.core.client.sftp.SftpClient.upload(SftpClient.java:89)
Creation of JIMFS file system during Application startup:
public class MockSftpServerInitializer implements ApplicationListener<ApplicationReadyEvent> {
@Override
public void onApplicationEvent(ApplicationReadyEvent event) {
SshServer sshd = SshServer.setUpDefaultServer();
sshd.setHost("localhost");
sshd.setPort(1234);
sshd.setCommandFactory(new ScpCommandFactory());
sshd.setKeyPairProvider(new SimpleGeneratorHostKeyProvider(new File("host-key.ser")));
sshd.setPublickeyAuthenticator(getPublickeyAuthenticator());
sshd.setFileSystemFactory(getInMemoryFileSystemFactory());
List<NamedFactory<Command>> sftpCommandFactory = new ArrayList<>();
sftpCommandFactory.add(new SftpSubsystemFactory());
sshd.setSubsystemFactories(sftpCommandFactory);
try {
sshd.start();
} catch (Exception e) {
throw new RuntimeException("Unable to start sshd", e);
}
}
private FileSystemFactory getInMemoryFileSystemFactory() {
return session -> getInMemoryFileSystem();
}
private FileSystem getInMemoryFileSystem() {
return Jimfs.newFileSystem(
Configuration.osX()
.toBuilder()
.setWorkingDirectory("/")
.setMaxSize(1024*1024*4)
.setDefaultAttributeValue("posix:permissions", "rwxrw-rw-")
.setAttributeViews("basic", "owner", "posix", "unix", "acl", "user")
.build());
}
}
File upload:
public class SftpClient {
public boolean upload(String source, String destination) {
Session session = null;
ChannelSftp sftpChannel = null;
try {
sftpProvider.addIdentity("Identity", privateKey.getBytes(), publicKey.getBytes(), null);
session = sftpProvider.getSession(username, host, port);
session.setConfig("StrictHostKeyChecking", "no");
session.connect();
Channel channel = session.openChannel("sftp");
channel.connect();
sftpChannel = (ChannelSftp) channel;
sftpChannel.put(source, destination);
log.info("Successful upload of file {} to SFTP server {}.", source, host);
return true;
} catch (SftpException | JSchException ex) {
log.error("Failed upload of file {} to SFTP server {}.", source, host);
log.error("{}", ex);
return false;
} finally {
if (sftpChannel != null) {
sftpChannel.disconnect();
}
if (session != null) {
session.disconnect();
}
}
}
}
I'm grateful for any hint on why this works locally but not in our docker container.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论