首页 > 解决方案 > 如何调试 org.apache.sshd.common.scp.ScpException: Received nack: Can not write to error?

问题描述

我正在编写一个用于测试具有基本功能的 SSH 连接的工具:连接、上传文件、下载文件。

我的 SftpTestServer 实现:

import org.apache.sshd.client.SshClient
import org.apache.sshd.client.scp.ScpClientCreator
import org.apache.sshd.client.session.ClientSession
import org.apache.sshd.common.file.virtualfs.VirtualFileSystemFactory
import org.apache.sshd.server.SshServer
import org.apache.sshd.server.auth.password.PasswordAuthenticator
import org.apache.sshd.server.keyprovider.SimpleGeneratorHostKeyProvider
import org.apache.sshd.server.scp.ScpCommandFactory
import org.apache.sshd.server.session.ServerSession
import org.apache.sshd.server.subsystem.SubsystemFactory
import org.apache.sshd.server.subsystem.sftp.SftpSubsystemFactory
import java.io.File
import java.nio.file.Paths
import java.util.*


class SftpTestServer(
    private val host: String,
    private val port: Int,
    private val rootDir: File,
    private val userName: String,
    private val password: String
) : TestServer {
    private val server: SshServer
    private val client: SshClient

    private fun session(): ClientSession {
        val session = client.connect(userName, server.host, server.port).verify().session
        session.addPasswordIdentity(password)
        session.auth().verify().isSuccess
        return session
    }

    override fun start() {
        server.start()
        client.start()
    }

    override fun stop() {
        client.stop()
        server.stop()
    }

    private fun setupServer(host: String, port: Int, rootDir: File, userName: String, pwd: String): SshServer {
        val sshd = SshServer.setUpDefaultServer()
        sshd.keyPairProvider = SimpleGeneratorHostKeyProvider(File(rootDir, "sshd_key.ser").toPath())
        sshd.fileSystemFactory = VirtualFileSystemFactory(Paths.get(rootDir.absolutePath))
        sshd.port = port
        sshd.host = host
        sshd.passwordAuthenticator = PasswordAuthenticator { username: String, password: String, _: ServerSession? -> username == userName && password == pwd }
        sshd.commandFactory = ScpCommandFactory()
        val factoryList: MutableList<SubsystemFactory> = ArrayList()
        factoryList.add(SftpSubsystemFactory())
        sshd.subsystemFactories = factoryList
        return sshd
    }

    fun upload(file: File) {
        val creator = ScpClientCreator.instance()
        val scpClient = creator.createScpClient(session())
        scpClient.upload(Paths.get(file.absolutePath), rootDir.absolutePath)
    }

    fun listFiles(): List<String> {
        return listOf()
    }

    init {
        server = setupServer(host, port, rootDir, userName, password)
        client = setupClient()
    }

    private fun setupClient(): SshClient {
        return SshClient.setUpDefaultClient()
    }
}

我的 SftpTestServerTest 实现:

import org.apache.commons.io.FileUtils
import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.*
import java.io.File

@Tag("servers")
class SftpTestServerTest {

    companion object {
        private const val HOST: String = "localhost"
        private const val PORT: Int = 23456
        private val TEST_FILE_RESOURCE: File = File("target/test-folder")
        private const val USERNAME: String = "username"
        private const val PASSWORD: String = "password"
    }

    private val server = SftpTestServer(HOST, PORT, TEST_FILE_RESOURCE, USERNAME, PASSWORD)

    @BeforeEach
    fun setUp() {
        server.start()

        FileUtils.deleteDirectory(TEST_FILE_RESOURCE)
        FileUtils.forceMkdir(TEST_FILE_RESOURCE)
    }

    @AfterEach
    fun tearDown() {
        server.stop()
    }

    @Test
    fun `should upload file from file path`() {
        val fileName = "src/test/resources/ssh_test_file.xml"
        val file = File(fileName)
        server.upload(file)
        assertThat(server.listFiles()).contains(fileName)
    }
}

令人惊讶的是,我在网上找不到太多关于我从中得到的错误的信息org.apache.sshd

org.apache.sshd.common.scp.ScpException:收到 nack:无法写入

如何调试此错误?

注意:我使用的是 Mac。不过,这个问题不应该是特定于操作系统的。

标签: kotlindebuggingapache-sshd

解决方案


问题是我使用 SSH 客户端连接到 SSH 服务器内的错误路径。

因此,我建议调试此问题:

  • 检查您对文件系统的读/写权限
  • 连接SSH服务器,检查文​​件夹结构
  • 在前面步骤的基础上,修复 SSH Client 连接问题

推荐阅读