AsyncSSH
AsyncSSH is an asynchronous Python library providing a client and server implementation of the SSHv2 protocol, built on top of the `asyncio` framework. It supports a wide range of features including shell, command, and subsystem channels, SFTP, SCP, port forwarding, and various authentication methods. The library is actively maintained, with a recent major version (2.x) and regular patch releases.
Warnings
- breaking AsyncSSH 2.0 and later requires Python 3.10 or newer. Users on older Python 3 versions (e.g., 3.6-3.9) must use AsyncSSH 1.x or upgrade their Python interpreter.
- breaking AsyncSSH 2.0+ mandates `cryptography` version 39.0 or higher. Upgrading `asyncssh` might require a concurrent upgrade of the `cryptography` dependency, which could have its own breaking changes if coming from a very old version.
- breaking In AsyncSSH 2.x, methods such as `asyncssh.create_server`, `asyncssh.listen`, `asyncssh.listen_reverse`, and `SSHClientConnection`'s server/forwarding methods now raise an exception (e.g., `asyncssh.ChannelListenError`) on listen failures, instead of returning `None`.
- breaking Starting with AsyncSSH 2.19.0, the `SSHClientConfig.load` method (and potentially related config parsing logic) gained new `canonical` and `final` arguments. Code that directly calls this method or relies on its previous signature might break.
- breaking Subclasses of `asyncssh.sftp.SFTPServer` that implement their own `__init__` method will need to update their signature in AsyncSSH 2.x to pass arguments through to the parent class.
- gotcha Before Python 3.10, using `asyncio.Lock()` as a global variable could lead to `RuntimeError: 'asyncio.Lock' object is not bound to a distinct event loop` when `asyncio.run()` creates a new event loop. While not specific to AsyncSSH, this is a common footgun in `asyncio`-heavy applications.
Install
-
pip install asyncssh -
pip install 'asyncssh[bcrypt,fido2,gssapi,ifaddr,pkcs11,pyopenssl,pywin32]'
Imports
- asyncssh
import asyncssh
- asyncio
import asyncio
Quickstart
import asyncio
import asyncssh
import os
async def run_client():
host = os.environ.get('SSH_HOST', 'localhost')
port = int(os.environ.get('SSH_PORT', 22))
username = os.environ.get('SSH_USERNAME', 'testuser')
password = os.environ.get('SSH_PASSWORD', '') # Or use client_keys=['/path/to/id_rsa']
try:
# Connect to the SSH server
conn = await asyncssh.connect(host, port=port, username=username, password=password)
# Run a command and get the result
result = await conn.run('echo "Hello from AsyncSSH!"', check=True)
print(f"Command: {result.command}")
print(f"Stdout: {result.stdout.strip()}")
print(f"Stderr: {result.stderr.strip()}")
print(f"Return code: {result.returncode}")
# Close the connection (async with handles this implicitly if used for conn)
conn.close()
except (asyncssh.Error, OSError) as exc:
print(f'SSH connection or command failed: {exc}')
if __name__ == '__main__':
# Note: For 'localhost' testing, you might need a local SSH server configured
# to accept connections for the specified username/password or client_key.
# Example to run:
# SSH_HOST=your_ssh_server SSH_USERNAME=your_user SSH_PASSWORD=your_pass python your_script.py
asyncio.run(run_client())