ssh2-python
ssh2-python provides Python bindings for the `libssh2` C library, offering a low-level, high-performance interface for SSHv2 protocol operations. It is currently at version 1.2.0.post1 and is actively maintained with regular releases that include updates to embedded libraries like `libssh2` and OpenSSL, and support for newer Python versions.
Common errors
-
Could NOT find OpenSSL, try to set the path to OpenSSL root folder in the system variable OPENSSL_ROOT_DIR (missing: OPENSSL_INCLUDE_DIR)
cause The `ssh2-python` build process (via `cmake` for `libssh2`) cannot locate the OpenSSL development libraries on your system, typically when installing from a source distribution without pre-compiled wheels.fixOn Debian/Ubuntu: `sudo apt-get install libssl-dev`. On RedHat/CentOS: `sudo yum install openssl-devel`. Ensure `cmake` is also installed. Alternatively, ensure your `pip` is up-to-date and try installing again to get a binary wheel: `pip install -U pip && pip install ssh2-python`. -
ERROR: Failed building wheel for ssh2-python` or `Command 'cmake ...' returned non-zero exit status 1.
cause Installation from source failed, often due to missing `libssh2` development libraries, `OpenSSL` development libraries, or `cmake`.fixInstall `cmake` and the development packages for `libssh2` and `OpenSSL` on your system. For example, on Ubuntu: `sudo apt-get install cmake libssh2-1-dev libssl-dev`. If a binary wheel is available for your platform and Python version, upgrading `pip` might resolve it by allowing the installation of the wheel: `pip install -U pip`. -
ssh2.exceptions.AuthenticationError: Publickey authentication failed
cause The provided public key or private key path is incorrect, the key is not authorized on the remote server, or the passphrase for the private key is wrong.fixVerify the paths to your public and private keys, ensure the public key is added to `~/.ssh/authorized_keys` on the remote server, and provide the correct passphrase if your private key is encrypted. Check `session.userauth_list()` to see available authentication methods on the server. -
ssh2.exceptions.SocketRecvError: Error reading SSH protocol banner
cause The remote host did not respond with a valid SSH protocol banner, or the connection dropped before the banner could be read. This can indicate that the target port is not an SSH server, a firewall issue, or an unresponsive server.fixVerify the IP address and port are correct for your SSH server. Check firewall rules on both the client and server. Ensure the remote SSH server is running and accessible.
Warnings
- gotcha The underlying `libssh2` library does not support sharing sessions across multiple threads. While `ssh2-python` itself is thread-safe, each thread should have its own `Session` object to avoid issues.
- breaking In version 1.2.0, several deprecated `libssh2` functions were removed from `ssh2.channel.Channel` and `ssh2.session.Session`. These include `receive_window_adjust`, `handle_extended_data`, `ignore_extended_data`, `startup`, `scp_recv`, and `scp_send`.
- gotcha When installing `ssh2-python` from source, users often encounter build failures due to missing `libssh2` and `OpenSSL` development headers or `cmake`. Binary wheels provided via pip usually embed these dependencies.
- gotcha Calling `ssh2.session.Session.methods()` without a valid SSH connection could lead to a segmentation fault in versions prior to 1.1.1.
- gotcha `ssh2-python` is a low-level binding to the `libssh2` C API. For most common SSH client tasks, a higher-level library like `parallel-ssh` (which uses `ssh2-python` internally) is recommended for ease of use and reduced boilerplate.
Install
-
pip install ssh2-python -
conda install -c conda-forge ssh2-python
Imports
- Session
from ssh2.session import Session
- SFTPHandle
from ssh2.sftp_handle import SFTPHandle
- Channel
from ssh2.channel import Channel
- exceptions
from ssh2 import exceptions
Quickstart
import socket
import os
from ssh2.session import Session
HOST = os.environ.get('SSH_HOST', 'localhost')
PORT = int(os.environ.get('SSH_PORT', '22'))
USERNAME = os.environ.get('SSH_USERNAME', 'user')
PASSWORD = os.environ.get('SSH_PASSWORD', 'password')
try:
# 1. Create a socket and connect
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect((HOST, PORT))
# 2. Initialize an SSH2 session
session = Session()
session.handshake(sock)
# 3. Authenticate with password
session.userauth_password(USERNAME, PASSWORD)
# 4. Check if authenticated
if not session.is_userauth_authenticated():
print("Authentication failed!")
exit(1)
print(f"Successfully authenticated to {HOST} as {USERNAME}")
# 5. Open a channel and execute a command
channel = session.open_session()
channel.execute('echo Hello from ssh2-python; uname -a')
# 6. Read output
size, data = channel.read()
while size > 0:
print(data.decode('utf-8').strip())
size, data = channel.read()
# 7. Get exit status
print(f"Command exit status: {channel.get_exit_status()}")
# 8. Close the channel and session
channel.close()
session.disconnect()
sock.close()
except exceptions.SSH2Error as e:
print(f"SSH2 Error: {e}")
except socket.error as e:
print(f"Socket Error: {e}")
except Exception as e:
print(f"An unexpected error occurred: {e}")