Skip to main content

SSHreader logo

Python Tests

SSHreader

SSHreader is a Python library for running commands on multiple servers in parallel. It wraps Paramiko and provides both a direct SSH client and a job-based interface for parallel SSH and local shell work. It also includes pydsh, a command-line tool for running commands across host lists.

SSHreader supports Python 3.11 and later.

Installation

Install the latest release from PyPI:

python -m pip install sshreader

Quick start

Use SSH to run commands in a single SSH session. SSHreader can use an SSH key, an SSH agent, or a password:

from sshreader import SSH

with SSH("myhost.example.com", username="jdoe", keyfile="~/.ssh/id_ed25519") as ssh:
    result = ssh.ssh_command("uname -a")
    print(result.stdout)
    print(result.return_code)

Use ServerJob and sshread to run jobs on multiple hosts. A job can contain multiple commands, which run sequentially on that host:

from sshreader import ServerJob, sshread

hosts = ["server1.example.com", "server2.example.com"]
jobs = [
    ServerJob(host, ["hostname", "uptime"], username="jdoe", keyfile="~/.ssh/id_ed25519")
    for host in hosts
]

finished_jobs = sshread(jobs, tcount=0)
for job in finished_jobs:
    print(job.name, job.status)
    for result in job.results:
        print(result.cmd, result.stdout, result.stderr, result.return_code)

tcount=0 selects a thread count based on the available CPUs and number of jobs. Use pcount=0 to enable multiprocessing; you can also combine process and thread workers. When using multiprocessing, put the call to sshread inside the standard if __name__ == "__main__": guard.

Each command result has cmd, stdout, stderr, and return_code fields. A ServerJob stores its command results in results and the sum of their return codes in status.

Other features

  • Run one or more commands over a reusable SSH connection with SSH.ssh_command.
  • Transfer files over SFTP with SSH.sftp_put and SSH.sftp_get.
  • Run local commands with shell_command (shell-free by default; use shell=True only when needed) or create local ServerJob instances with run_local=True.
  • Use Hook objects to run functions before or after a job, including hooks that use its established SSH connection.
  • Discover the current username, SSH keys, and agent keys with envvars().
  • Configure connection and command timeouts, SSH ports, output handling, and worker counts.

See the documentation for detailed API guides and examples.

pydsh

Installing SSHreader also installs the pydsh command. It accepts hostlist expressions and runs a command across the expanded hosts:

pydsh -w 'web[01-10].example.com' 'uname -r'

By default, pydsh uses the current username and available SSH keys or agent, prompting for a password when needed. You can specify credentials and group or coalesce output:

pydsh -u jdoe -k ~/.ssh/id_ed25519 -D -w 'web[01-10].example.com' 'uname -r'

Use pydsh --help to see all options. With -F, the command argument is treated as a script file; the script must start with a shebang (#!), and --confirm skips the execution confirmation prompt.

Development

To set up a local development environment and run the tests:

uv sync --group test
uv run --group test pytest

Run lint and type checks with:

uv run --group test ruff check sshreader tests
uv run --group test ty check sshreader

Contributing

Bug reports, feature requests, and code contributions are welcome. Please open an issue with a minimal example and relevant traceback when reporting a problem. Contributions can be submitted as pull requests to the GitHub repository.

License

SSHreader is released under the GNU Lesser General Public License v3.0 or later. See LICENSE and LICENSE.lesser for the license texts.

Metadata

Release files for sshreader 7.0.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for sshreader 7.0.0
File Size Uploaded Provenance
sshreader-7.0.0.tar.gz 38.9 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for sshreader 7.0.0
File Interpreter ABI Platform
sshreader-7.0.0-py3-none-any.whl Python 3 none any Details

Total release size: 74.9 kB

Release files / sshreader-7.0.0.tar.gz

Download URL sshreader-7.0.0.tar.gz
Size 38.9 kB
Tags Source
SHA-256 checksum
How to use checksums
7f53dcb17a68cb6b03ef62a7d2e39dc811fb6f16b924252537990c1306c5fb8d
BLAKE2b-256 checksum
How to use checksums
be8df94664ced5cf4491cfd8191b5839ef0e7e7475e0b74bf30515356c3d4a6f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.13.5 {"installer":{"name":"uv","version":"0.13.5","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / sshreader-7.0.0-py3-none-any.whl

Download URL sshreader-7.0.0-py3-none-any.whl
Size 36.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
c9e552ddec9b05ff6dad748187c3cb8ff741945974472f9e915c5ab952eb93e5
BLAKE2b-256 checksum
How to use checksums
978b32bb28e344ebbb5a962c3a834770c0627cc2bd98cf7dc45ef04dea3472fc
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.13.5 {"installer":{"name":"uv","version":"0.13.5","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Security for sshreader 7.0.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

7.0.0 This release

2 release files No provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page