Skip to main content

Execution helpers for simplified usage of subprocess and ssh.

Project description

exec-helpers

https://travis-ci.org/python-useful-helpers/exec-helpers.svg?branch=master https://coveralls.io/repos/github/python-useful-helpers/exec-helpers/badge.svg?branch=master Documentation Status https://img.shields.io/pypi/v/exec-helpers.svg https://img.shields.io/pypi/pyversions/exec-helpers.svg https://img.shields.io/pypi/status/exec-helpers.svg https://img.shields.io/github/license/python-useful-helpers/exec-helpers.svg

Execution helpers for simplified usage of subprocess and ssh. Why another subprocess wrapper and why no clear paramiko?

Historically paramiko offers good ssh client, but with specific limitations: you can call command with timeout, but without receiving return code, or call command and wait for return code, but without timeout processing.

In the most cases, we are need just simple SSH client with comfortable API for calls, calls via SSH proxy and checking return code/stderr. This library offers this functionality with connection memorizing, deadlock free polling and friendly result objects (with inline decoding of YAML, JSON, binary or just strings). In addition this library offers the same API for subprocess calls, but with specific limitation: no parallel calls (for protection from race conditions).

Pros:

Python 2.7
Python 3.4
Python 3.5
Python 3.6
PyPy
PyPy3 3.5+

This package includes:

  • SSHClient - historically the first one helper, which used for SSH connections and requires memorization due to impossibility of connection close prediction. Several API calls for sFTP also presents.

  • SSHAuth - class for credentials storage. SSHClient does not store credentials as-is, but uses SSHAuth for it. Objects of this class can be copied between ssh connection objects, also it used for execute_through_host.

  • Subprocess - subprocess.Popen wrapper with timeouts, polling and almost the same API, as SSHClient (except specific flags, like cwd for subprocess and get_tty for ssh).

  • ExecResult - class for execution results storage. Contains exit code, stdout, stderr and getters for decoding as JSON, YAML, string, bytearray and brief strings (up to 7 lines).

  • ExitCodes - enumerator for standard Linux exit codes. BASH return codes (broduced from signal codes) also available.

Usage

SSHClient

Basic initialization of SSHClient can be done without construction of specific objects:

client = exec_helpers.SSHClient(host, username="username", password="password")

If ssh agent is running - keys will be collected by paramiko automatically, but if keys are in specific location - it should be loaded manually and provided as iterable object of paramiko.RSAKey.

For advanced cases or re-use of credentials, SSHAuth object should be used. It can be collected from connection object via property auth.

Creation from scratch:

auth = exec_helpers.SSHAuth(
    username='username',  # type: typing.Optional[str]
    password='password',  # type: typing.Optional[str]
    key=None,  # type: typing.Optional[paramiko.RSAKey]
    keys=None,  # type: typing.Optional[typing.Iterable[paramiko.RSAKey]],
    key_filename=None,  # type: typing.Union[typing.List[str], str, None]
    passphrase=None,  # type: typing.Optional[str]
)

Key is a main connection key (always tried first) and keys are alternate keys. Key filename is afilename or list of filenames with keys, which should be loaded. Passphrase is an alternate password for keys, if it differs from main password. If main key now correct for username - alternate keys tried, if correct key found - it became main. If no working key - password is used and None is set as main key.

Context manager is available, connection is closed and lock is released on exit from context.

Subprocess

No initialization required. Context manager is available, subprocess is killed and lock is released on exit from context.

Base methods

Main methods are execute, check_call and check_stderr for simple executing, executing and checking return code and executing, checking return code and checking for empty stderr output. This methods are almost the same for SSHCleint and Subprocess, except specific flags.

result = helper.execute(
    command,  # type: str
    verbose=False,  # type: bool
    timeout=1 * 60 * 60,  # type: typing.Optional[int]
    **kwargs
)
result = helper.check_call(
    command,  # type: str
    verbose=False,  # type: bool
    timeout=1 * 60 * 60,  # type: typing.Optional[int]
    error_info=None,  # type: typing.Optional[str]
    expected=None,  # type: typing.Optional[typing.Iterable[int]]
    raise_on_err=True,  # type: bool
    **kwargs
)
result = helper.check_stderr(
    command,  # type: str
    verbose=False,  # type: bool
    timeout=1 * 60 * 60,  # type: typing.Optional[int]
    error_info=None,  # type: typing.Optional[str]
    raise_on_err=True,  # type: bool
)

If no STDOUT or STDERR required, it is possible to disable this FIFO pipes via **kwargs with flags open_stdout=False and open_stderr=False.

The next command level uses lower level and kwargs are forwarded, so expected exit codes are forwarded from check_stderr. Implementation specific flags are always set via kwargs.

If required to mask part of command from logging, log_mask_re attribute can be set global over instance or providden with command. All regex matched groups will be replaced by ‘<*masked*>’.

result = helper.execute(
    command="AUTH='top_secret_key'; run command",  # type: str
    verbose=False,  # type: bool
    timeout=1 * 60 * 60,  # type: typing.Optional[int]
    log_mask_re=r"AUTH\s*=\s*'(\w+)'"  # type: typing.Optional[str]
)

result.cmd will be equal to AUTH=’<*masked*>’; run command

ExecResult

Execution result object has a set of useful properties:

  • cmd - Command

  • exit_code - Command return code. If possible to decode using enumerators for Linux -> it used.

  • stdin -> str. Text representation of stdin.

  • stdout -> typing.Tuple[bytes]. Raw stdout output.

  • stderr -> typing.Tuple[bytes]. Raw stderr output.

  • stdout_bin -> bytearray. Binary stdout output.

  • stderr_bin -> bytearray. Binary stderr output.

  • stdout_str -> six.text_types. Text representation of output.

  • stderr_str -> six.text_types. Text representation of output.

  • stdout_brief -> six.text_types. Up to 7 lines from stdout (3 first and 3 last if >7 lines).

  • stderr_brief -> six.text_types. Up to 7 lines from stderr (3 first and 3 last if >7 lines).

  • stdout_json - STDOUT decoded as JSON.

  • stdout_yaml - STDOUT decoded as YAML.

  • timestamp -> typing.Optional(datetime.datetime). Timestamp for received exit code.

SSHClient specific

SSHClient commands support get_pty flag, which enables PTY open on remote side. PTY width and height can be set via kwargs, dimensions in pixels are always 0x0.

Possible to call commands in parallel on multiple hosts if it’s not produce huge output:

results = SSHClient.execute_together(
    remotes,  # type: typing.Iterable[SSHClient]
    command,  # type: str
    timeout=1 * 60 * 60,  # type: typing.Optional[int]
    expected=None,  # type: typing.Optional[typing.Iterable[int]]
    raise_on_err=True  # type: bool
)
results  # type: typing.Dict[typing.Tuple[str, int], exec_result.ExecResult]

Results is a dict with keys = (hostname, port) and and results in values. By default execute_together raises exception if unexpected return code on any remote.

For execute through SSH host can be used execute_through_host method:

result = client.execute_through_host(
    hostname,  # type: str
    command,  # type: str
    auth=None,  # type: typing.Optional[SSHAuth]
    target_port=22,  # type: int
    timeout=1 * 60 * 60,  # type: typing.Optional[int]
    verbose=False,  # type: bool
    get_pty=False,  # type: bool
)

Where hostname is a target hostname, auth is an alternate credentials for target host.

SSH client implements fast sudo support via context manager: Commands will be run with sudo enforced independently from client settings for normal usage:

with client.sudo(enforce=True):
    ...

Commands will be run without sudo independently from client settings for normal usage:

with client.sudo(enforce=False):
    ...

“Permanent client setting”:

client.sudo_mode = mode  # where mode is True or False

SSH Client supports sFTP for working with remote files:

with client.open(path, mode='r') as f:
    ...

For fast remote paths checks available methods:

  • exists(path) -> bool

>>> conn.exists('/etc/passwd')
True
  • stat(path) -> paramiko.sftp_attr.SFTPAttributes

>>> conn.stat('/etc/passwd')
<SFTPAttributes: [ size=1882 uid=0 gid=0 mode=0o100644 atime=1521618061 mtime=1449733241 ]>
>>> str(conn.stat('/etc/passwd'))
'-rw-r--r--   1 0        0            1882 10 Dec 2015  ?'
  • isfile(path) -> bool

>>> conn.isfile('/etc/passwd')
True
  • isdir(path) -> bool

>>> conn.isdir('/etc/passwd')
False

Additional (non-standard) helpers:

  • mkdir(path: str) - execute mkdir -p path

  • rm_rf(path: str) - execute rm -rf path

  • upload(source: str, target: str) - upload file or from source to target using sFTP.

  • download(destination: str, target: str) - download file from target to destination using sFTP.

Subprocess specific

Kwargs set properties:

  • cwd - working directory.

  • env - environment variables dict.

Testing

The main test mechanism for the package exec-helpers is using tox. Available environments can be collected via tox -l

CI systems

For code checking several CI systems is used in parallel:

  1. Travis CI: is used for checking: PEP8, pylint, bandit, installation possibility and unit tests. Also it’s publishes coverage on coveralls.

  2. coveralls: is used for coverage display.

Project details


Release history Release notifications | RSS feed

This version

1.3.1

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

exec-helpers-1.3.1.tar.gz (54.1 kB view details)

Uploaded Source

Built Distributions

exec_helpers-1.3.1-py2-none-any.whl (39.7 kB view details)

Uploaded Python 2

exec_helpers-1.3.1-cp36-cp36m-manylinux1_x86_64.whl (1.9 MB view details)

Uploaded CPython 3.6m

exec_helpers-1.3.1-cp36-cp36m-manylinux1_i686.whl (1.8 MB view details)

Uploaded CPython 3.6m

exec_helpers-1.3.1-cp35-cp35m-manylinux1_x86_64.whl (1.8 MB view details)

Uploaded CPython 3.5m

exec_helpers-1.3.1-cp35-cp35m-manylinux1_i686.whl (1.7 MB view details)

Uploaded CPython 3.5m

exec_helpers-1.3.1-cp34-cp34m-manylinux1_x86_64.whl (1.9 MB view details)

Uploaded CPython 3.4m

exec_helpers-1.3.1-cp34-cp34m-manylinux1_i686.whl (1.8 MB view details)

Uploaded CPython 3.4m

File details

Details for the file exec-helpers-1.3.1.tar.gz.

File metadata

File hashes

Hashes for exec-helpers-1.3.1.tar.gz
Algorithm Hash digest
SHA256 8253e6f954596d3fb92ea2f1ccfa8e78ca83af3856909be038a3aca1d489fb0f
MD5 73dae0c9ceb4aa80180ec5a37fe5bb13
BLAKE2b-256 11d52dbd312e8451befcdc1cf69b2971cce0673312c0e8e11a7db61d4546c391

See more details on using hashes here.

File details

Details for the file exec_helpers-1.3.1-py2-none-any.whl.

File metadata

File hashes

Hashes for exec_helpers-1.3.1-py2-none-any.whl
Algorithm Hash digest
SHA256 ea58033eb52a94c503b0883bece67703acb976ce99b278b3042b7fc877051ac3
MD5 5599ee25a36bc4d6e6b9a42fc1e3e9ba
BLAKE2b-256 5907dc82d5c5da5308912296279d3c60c15727f0389b6321fa9c711c9686466a

See more details on using hashes here.

File details

Details for the file exec_helpers-1.3.1-cp36-cp36m-manylinux1_x86_64.whl.

File metadata

File hashes

Hashes for exec_helpers-1.3.1-cp36-cp36m-manylinux1_x86_64.whl
Algorithm Hash digest
SHA256 c9774c9487239e46fa64b126e8dab16f31a780ecaceae575c368af25850faa50
MD5 65837f1d882de5bada1f974417f7047e
BLAKE2b-256 84ab67afc6f96b52c6d7e6c7e436b7d312c0f2fcc3ab31e620c9991b0a80c7e3

See more details on using hashes here.

File details

Details for the file exec_helpers-1.3.1-cp36-cp36m-manylinux1_i686.whl.

File metadata

File hashes

Hashes for exec_helpers-1.3.1-cp36-cp36m-manylinux1_i686.whl
Algorithm Hash digest
SHA256 6e72ee104d7f49a072445cbb68b1c4ed3e9272fdbeba62f013421d84d660a96d
MD5 064f03bdb4f808be6570ad0497ff325d
BLAKE2b-256 350e7cd3e5e51208d1fd8646e69e8829768c4013f1151a73ec969b62a9f55ada

See more details on using hashes here.

File details

Details for the file exec_helpers-1.3.1-cp35-cp35m-manylinux1_x86_64.whl.

File metadata

File hashes

Hashes for exec_helpers-1.3.1-cp35-cp35m-manylinux1_x86_64.whl
Algorithm Hash digest
SHA256 72a5f84cc5783dc01d7fbce5943835de2da455d740099eb1c8c095c88e06e881
MD5 67d16950b810ee210a9770fbd4b90cea
BLAKE2b-256 fb6f742aa02fa1f1193348ee868118f2deaf65aa91b7313af8607ff5b81ed4ce

See more details on using hashes here.

File details

Details for the file exec_helpers-1.3.1-cp35-cp35m-manylinux1_i686.whl.

File metadata

File hashes

Hashes for exec_helpers-1.3.1-cp35-cp35m-manylinux1_i686.whl
Algorithm Hash digest
SHA256 dc88c840527b43fcd061492ec655a3697a4e9b576c1c89fcc312da8354f538c8
MD5 881669d045efdd9d403109777ff1d5fd
BLAKE2b-256 14ffd6cfdd28150925033e7e2b3df499dfe53da34637da2c03863e3229b97277

See more details on using hashes here.

File details

Details for the file exec_helpers-1.3.1-cp34-cp34m-manylinux1_x86_64.whl.

File metadata

File hashes

Hashes for exec_helpers-1.3.1-cp34-cp34m-manylinux1_x86_64.whl
Algorithm Hash digest
SHA256 e65df350297f945b0f68f189d79c2542aebcf55b42f5287bcdcdf3e21fa29396
MD5 e6d94555039cc81fe56bed3dc9db1544
BLAKE2b-256 f2387e7f4c0f6c5a2be20149c8b204db2af181b12842bf2f089a7a22aab9e023

See more details on using hashes here.

File details

Details for the file exec_helpers-1.3.1-cp34-cp34m-manylinux1_i686.whl.

File metadata

File hashes

Hashes for exec_helpers-1.3.1-cp34-cp34m-manylinux1_i686.whl
Algorithm Hash digest
SHA256 fa939bb5defc85fb42da7df558d8c566684eed6e3201f3d4bf021af8d8db3b50
MD5 42fc4309efd5a935fe0e01d693c1bd70
BLAKE2b-256 dc9afd8badf3e4b7f7be2efab9fc25a7b12643bcb0ae8581f5c22bc4a749b763

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page