asyncssh
asyncssh copied to clipboard
Why is the loop waiting for command execution endless?
class BaseSSHClientSession(asyncssh.SSHClientSession):
def __init__(self):
self._stdin = None
self._stdout = None
self._stderr = None
self._recv_ready = asyncio.Event()
self._output_buffer = ""
self._closed = asyncio.Event()
self._eof_received = False
def connection_made(self, chan):
self._stdin = chan
self._stdout = chan
self._stderr = chan
print("Connection made")
def data_received(self, data, datatype):
print(f"Data received: {data}")
self._output_buffer += data
self._recv_ready.set()
def eof_received(self):
print("EOF received")
self._eof_received = True
self._recv_ready.set()
def connection_lost(self, exc):
if exc:
print(f'SSH session error: {exc}')
else:
print("SSH session closed")
self._recv_ready.set()
self._closed.set()
async def run_command(self, command: str, timeout: Optional[int] = None) -> str:
self._recv_ready.clear()
self._output_buffer = ""
self._eof_received = False
self._stdin.write(command + '\n')
print("Command sent")
while not self._eof_received:
try:
await asyncio.wait_for(self._recv_ready.wait(), timeout)
self._recv_ready.clear()
except asyncio.TimeoutError:
raise CommandSshException(f"Command '{command}' timed out")
print("Command received")
output = self._output_buffer
self._output_buffer = ""
return output
**The problem is in this block of code**
while not self._eof_received:
try:
await asyncio.wait_for(self._recv_ready.wait(), timeout)
self._recv_ready.clear()
except asyncio.TimeoutError:
raise CommandSshException(f"Command '{command}' timed out")
You appear to be opening an interactive shell session and writing a command to stdin. However, you are waiting for EOF to be received. That'll never happen, as the server will simply go back and output the shell prompt after the command completes. It is up to you to find a way to know when the command has finished running and you're sitting back at a remote shell prompt again.
Since you are using callbacks, you'd have to parse the output coming in via data_received() to determine when the command output is done and it's time to send another command to the remote shell. Alternately, you could try sending something like "command" followed by "exit" in a single command (e.g. "command; exit"). That might cause the shell to exit, at which point you'd get the EOF you were expecting.
Closing due to inactivity. Feel free to reopen this or open a new issue if you need anything else.