You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I have not found any examples of what I am trying to do in official documentation.
I have two tests here (in kotlin):
packageminatestimportcom.google.common.truth.Truthimportorg.apache.sshd.client.SshClientimportorg.junit.jupiter.api.MethodOrderer.OrderAnnotationimportorg.junit.jupiter.api.Orderimportorg.junit.jupiter.api.Testimportorg.junit.jupiter.api.TestMethodOrderimportorg.junit.jupiter.api.Timeoutimportorg.slf4j.LoggerFactoryimportorg.springframework.beans.factory.annotation.Autowiredimportorg.springframework.boot.test.context.SpringBootTestimportorg.springframework.test.context.ActiveProfilesimportreactor.kotlin.test.testimportjava.time.Duration.ofSecondsimportjava.util.concurrent.CountDownLatchimportjava.util.concurrent.TimeUnit.SECONDSval client =SshClient.setUpDefaultClient().apply {
start()
}
@Test
funsanityTest() {
val instance = requestor.getExistingInstance(existingInstance).block(ofSeconds(5))
val ipv4 = instance.getPublicIpv4Address()
val connection = client.connect(
"root",
ipv4,
22
).verify(ofSeconds(5))
val output = connection
.session
.run {
auth().verify(ofSeconds(5))
executeRemoteCommand("uptime")
}
logger.info("Output: $output")
}
@Test
funsecondSanityNowAsync() {
val instance = requestor
.getExistingInstance(existingInstance)
.block(ofSeconds(10))
val connected = client.connect("root", instance.getPublicIpv4Address(), 22)
val blocker =CountDownLatch(1)
connected.addListener { conn ->
logger.info("Connected: $conn")
val sesh = conn.session
val auth = sesh.auth().addListener { authed ->
conn.verify(0)
authed.verify(0)
logger.info("Authed: $authed")
val output = sesh.executeRemoteCommand("uptime")
logger.info("Output: $output")
Truth.assertThat(output).contains("load")
// NOTIFY OF COMPLETION
blocker.countDown()
}
}
assert(blocker.await(10, SECONDS))
}
The synchronous one works just fine. I call verify twice and then I am set up to go. However I'm going for an async architecture and would rather do something like the second as it will eventually be integrated into a project reactor application.
The first one runs just fine, the second one hangs forever on the connected.session.executeRemoteCommand(...). Setting a breakpoint it makes it all the way to the second listener (i.e. I get the "Authed: ..." log message) and then never makes it to the "Output: ".
Actual behavior
The test fails to complete in any amount of time.
Expected behavior
The executeRemoteCommand should execute
Relevant log output
From the run where it hangs:
2023-10-24T14:27:51,113 DEBUG [sshd-SshClient[15fdd1f2]-nio2-thread-9] o.a.s.c.s.AbstractClientSession: createExecChannel(ClientSessionImpl[root@/142.93.54.117:22])[uptime] created id=0 - PTY=null
2023-10-24T14:27:51,113 DEBUG [sshd-SshClient[15fdd1f2]-nio2-thread-9] o.a.s.c.c.AbstractClientChannel: open(ChannelExec[id=0, recipient=-1]-ClientSessionImpl[root@/142.93.54.117:22]) Send SSH_MSG_CHANNEL_OPEN - type=session
2023-10-24T14:27:51,113 DEBUG [sshd-SshClient[15fdd1f2]-nio2-thread-9] o.a.s.c.s.h.AbstractSession: encode(ClientSessionImpl[root@/142.93.54.117:22]) packet #7 sending command=90[SSH_MSG_CHANNEL_OPEN] len=24
2023-10-24T14:27:51,113 DEBUG [sshd-SshClient[15fdd1f2]-nio2-thread-9] o.a.s.c.i.n.Nio2Session: writeBuffer(Nio2Session[local=/192.168.86.247:63735, remote=/142.93.54.117:22]) writing 60 bytes
java.lang.AssertionError: Assertion failed (on the countdownlatch block)
The last few logs from when it runs successfully:
2023-10-24T14:15:39,701 DEBUG [main] o.a.s.c.s.AbstractClientSession: createExecChannel(ClientSessionImpl[root@/142.93.54.117:22])[uptime] created id=0 - PTY=null
2023-10-24T14:15:39,702 DEBUG [main] o.a.s.c.c.AbstractClientChannel: open(ChannelExec[id=0, recipient=-1]-ClientSessionImpl[root@/142.93.54.117:22]) Send SSH_MSG_CHANNEL_OPEN - type=session
2023-10-24T14:15:39,702 DEBUG [main] o.a.s.c.s.h.AbstractSession: encode(ClientSessionImpl[root@/142.93.54.117:22]) packet #7 sending command=90[SSH_MSG_CHANNEL_OPEN] len=24
2023-10-24T14:15:39,702 DEBUG [main] o.a.s.c.i.n.Nio2Session: writeBuffer(Nio2Session[local=/192.168.86.247:63598, remote=/142.93.54.117:22]) writing 60 bytes
2023-10-24T14:15:40,374 DEBUG [sshd-SshClient[15fb7a32]-nio2-thread-11] o.a.s.c.s.h.AbstractSession: doHandleMessage(ClientSessionImpl[root@/142.93.54.117:22]) process #8 SSH_MSG_GLOBAL_REQUEST
2023-10-24T14:15:40,375 DEBUG [sshd-SshClient[15fb7a32]-nio2-thread-11] o.a.s.c.s.h.AbstractConnectionService: globalRequest(ClientConnectionService[ClientSessionImpl[root@/142.93.54.117:22]]) received SSH_MSG_GLOBAL_REQUEST hostkeys-00@openssh.com want-reply=false
Other information
No response
The text was updated successfully, but these errors were encountered:
The basic problem here is a mixture of asynchronous mechanisms (futures, and listeners) and then a listener making a synchronous executeRemoteCommand call.
The immediate cause for blocking is that internally a lock is held, which prevents any more incoming messages for that session being handled until that listener is done. "Fixing" this in a transparent and scalable way inside the library looks very difficult.
A quick work-around for your case would be to make that listener use a different thread for everything after logger.info("Authed: $authed").
Version
2.11.0
Bug description
I have not found any examples of what I am trying to do in official documentation.
I have two tests here (in kotlin):
The synchronous one works just fine. I call verify twice and then I am set up to go. However I'm going for an async architecture and would rather do something like the second as it will eventually be integrated into a project reactor application.
The first one runs just fine, the second one hangs forever on the
connected.session.executeRemoteCommand(...)
. Setting a breakpoint it makes it all the way to the second listener (i.e. I get the "Authed: ..." log message) and then never makes it to the "Output: ".Actual behavior
The test fails to complete in any amount of time.
Expected behavior
The
executeRemoteCommand
should executeRelevant log output
Other information
No response
The text was updated successfully, but these errors were encountered: