ssh-python Library
ssh-python provides robust Python bindings for the `libssh` C library, enabling programmatic interaction with SSH servers. It offers functionalities for connecting, authenticating, executing commands, and managing SSH channels. The library is actively maintained, with version 1.2.0.post1 being the latest stable release, typically releasing minor updates every few months with periodic patch versions.
Common errors
-
ModuleNotFoundError: No module named 'ssh'
cause The `ssh-python` library (which provides the `ssh` module) is not installed in the active Python environment or is not on the Python path.fixInstall the library: `pip install ssh-python`. Ensure your virtual environment is activated if you are using one. -
ssh.AuthError: Authentication failed
cause The provided username, password, or private key is incorrect, or the SSH server denied the authentication attempt for other reasons (e.g., user not found, public key not authorized).fixVerify your credentials (username, password, private key path). Check permissions of private key files (usually `chmod 600`). Review SSH server logs for authentication details (`/var/log/auth.log` on Linux). -
ssh.SSHException: Could not resolve hostname ...
cause The hostname or IP address provided for connection could not be resolved by DNS, or the server is unreachable/down.fixCheck the hostname or IP address for typos. Verify network connectivity to the target host (e.g., `ping hostname`). Ensure the SSH service is running on the remote server. -
AttributeError: 'Channel' object has no attribute 'get_exit_status'
cause You are trying to call `get_exit_status()` on an `ssh.channel.Channel` object, but your installed `ssh-python` version is older than 1.2.0, where this method was introduced.fixUpgrade your `ssh-python` library to version 1.2.0 or newer: `pip install --upgrade ssh-python`.
Warnings
- breaking Older Python versions (e.g., <3.8) are no longer officially supported by ssh-python versions >= 1.1.0. Running on unsupported versions may lead to build failures or runtime issues.
- gotcha Although official wheels embed `libssh`, source installations (e.g., via `pip install --no-binary :all: ssh-python` or on unsupported platforms) require `libssh` development packages to be present on the system. This typically means `libssh-dev` (Debian/Ubuntu) or `libssh-devel` (RHEL/Fedora).
- breaking API features such as `channel.get_exit_status()` were introduced in `ssh-python` version 1.2.0. Attempting to use these features on older versions will result in an `AttributeError`.
- gotcha Authentication failures are common due to incorrect credentials, invalid private key paths/permissions, or server-side configuration issues. The `AuthError` exception should be specifically handled.
Install
-
pip install ssh-python
Imports
- Session
from ssh import Session
- AuthError
from ssh import AuthError
- SSHException
from ssh import SSHException
- SSH_OPTIONS_HOST
from ssh import SSH_OPTIONS_HOST
- SSH_AUTH_SUCCESS
from ssh import SSH_AUTH_SUCCESS
Quickstart
import ssh
import os
try:
# Initialize an SSH session
session = ssh.Session()
# Set connection options
session.options_set(ssh.SSH_OPTIONS_HOST, os.environ.get('SSH_HOST', 'localhost'))
session.options_set(ssh.SSH_OPTIONS_PORT, int(os.environ.get('SSH_PORT', 22)))
# Connect to the SSH server
session.connect()
print(f"Connected to {session.options_get(ssh.SSH_OPTIONS_HOST)}:{session.options_get_int(ssh.SSH_OPTIONS_PORT)}")
# Authenticate using password
username = os.environ.get('SSH_USER', 'guest')
password = os.environ.get('SSH_PASSWORD', 'guestpass') # DO NOT hardcode passwords in production
if session.userauth_password(username, password) != ssh.SSH_AUTH_SUCCESS:
raise ssh.AuthError("Authentication failed")
print(f"Authenticated as {username}")
# Open a channel for executing commands
channel = session.channel_session()
channel.open_session()
# Execute a command
command = "echo Hello from ssh-python!"
print(f"Executing command: '{command}'")
channel.request_exec(command)
# Read output
stdout = channel.read_stdout(2048)
stderr = channel.read_stderr(2048)
exit_status = channel.get_exit_status()
print(f"--- STDOUT ---\n{stdout.decode().strip()}")
print(f"--- STDERR ---\n{stderr.decode().strip()}")
print(f"Exit Status: {exit_status}")
# Close the channel and session
channel.close()
print("Channel closed.")
session.disconnect()
print("Session disconnected.")
except ssh.AuthError as e:
print(f"Authentication Error: {e}")
except ssh.SSHException as e:
print(f"SSH Connection Error: {e}")
except Exception as e:
print(f"An unexpected error occurred: {e}")