|
| 1 | +*********** |
| 2 | +Quickstart |
| 3 | +*********** |
| 4 | + |
| 5 | +First, make sure that `parallel-ssh` is `installed <installation>`_. |
| 6 | + |
| 7 | +Run a command on hosts in parallel |
| 8 | +------------------------------------ |
| 9 | + |
| 10 | +The most basic usage of `parallel-ssh` is, unsurprisingly, to run a command on multiple hosts in parallel. |
| 11 | + |
| 12 | +Examples here will be using `print` as a function, for which a future import is needed for Python `2.7`. |
| 13 | + |
| 14 | +Make a list of the hosts to run on:: |
| 15 | + |
| 16 | + from __future__ import print_function |
| 17 | + |
| 18 | + hosts = ['host1', 'host2', 'host3', 'host4'] |
| 19 | + |
| 20 | +Where `host1` to `host4` are valid host names. IP addresses may also be used. |
| 21 | + |
| 22 | +Create a client for these hosts:: |
| 23 | + |
| 24 | + client = ParallelSSHClient(hosts) |
| 25 | + |
| 26 | +The client object can, and should, be reused. Existing connections to hosts will remain alive as long as the client object is kept alive. Subsequent commands to the same host(s) will reuse their existing connection and benefit from much faster response times. |
| 27 | + |
| 28 | +Now one or more commands can be run via the client:: |
| 29 | + |
| 30 | + output = client.run_command('whoami') |
| 31 | + |
| 32 | +At this point the remote command has started executing in parallel. |
| 33 | + |
| 34 | +Output is keyed by host and contains a host output object. From that, SSH output is available |
| 35 | + |
| 36 | +Authentication |
| 37 | +---------------- |
| 38 | + |
| 39 | +By default `parallel-ssh` will use an available SSH agent's credentials to login to hosts via private key authentication. |
| 40 | + |
| 41 | +User/Password authentication |
| 42 | +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |
| 43 | + |
| 44 | +User/password authentication can be used by providing user name and password credentials:: |
| 45 | + |
| 46 | + client = ParallelSSHClient(hosts, user='my_user', password='my_pass') |
| 47 | + |
| 48 | +Programmatic Private Key authentication |
| 49 | +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |
| 50 | + |
| 51 | +It is also possible to programmatically use a private key for authentication. |
| 52 | + |
| 53 | +The helper function `pssh.utils.load_private_key` is provided to easily load all possible key types. It takes either a file path or a file-like object. |
| 54 | + |
| 55 | +File path:: |
| 56 | + |
| 57 | + from pssh.utils import load_private_key |
| 58 | + pkey = load_private_key('my_pkey.pem') |
| 59 | + client = ParallelSSHClient(hosts, pkey=pkey) |
| 60 | + |
| 61 | +File object:: |
| 62 | + |
| 63 | + from pssh.utils import load_private_key |
| 64 | + pkey = load_private_key(open('my_pkey.pem')) |
| 65 | + client = ParallelSSHClient(hosts, pkey=pkey) |
| 66 | + |
| 67 | + |
| 68 | +Standard Output |
| 69 | +---------------- |
| 70 | + |
| 71 | +Standard output, aka `stdout` for `host1`:: |
| 72 | + |
| 73 | + for line in output['host1']: |
| 74 | + print(line) |
| 75 | + |
| 76 | +Output:: |
| 77 | + |
| 78 | + <your username here> |
| 79 | + |
| 80 | +There is nothing special needed to ensure output is available. |
| 81 | + |
| 82 | +Please note that retrieving all of a command's standard output by definition requires that the command has completed. |
| 83 | + |
| 84 | +Iterating over the `stdout` attribute for any host will therefor *block* until that host's command has completed unless interrupted. |
| 85 | + |
| 86 | + |
| 87 | +All hosts iteration |
| 88 | +^^^^^^^^^^^^^^^^^^^^^ |
| 89 | + |
| 90 | +Of course, iterating over all hosts can also be done the same way:: |
| 91 | + |
| 92 | + for host, host_output in output.items(): |
| 93 | + for line in host_output: |
| 94 | + print("Host %s: %s" % (host, line)) |
| 95 | + |
| 96 | +Exit codes |
| 97 | +------------- |
| 98 | + |
| 99 | +Exit codes are available on the host output object. |
| 100 | + |
| 101 | +First, ensure that all commands have finished and exit codes gathered by joining on the output object, then iterate over all hosts:: |
| 102 | + |
| 103 | + client.join(output) |
| 104 | + for host, host_output in output.items(): |
| 105 | + print("Host %s exit code: %s" % (host, host_output.exit_code)) |
| 106 | + |
| 107 | +Host Logger |
| 108 | +------------ |
| 109 | + |
| 110 | +There is a built in host logger that can be enabled to log output from remote hosts. The helper function ``pssh.utils.enable_host_logger`` will enable host logging to standard output, for example :: |
| 111 | + |
| 112 | + from pssh.utils import enable_host_logger |
| 113 | + enable_host_logger() |
| 114 | + client.join(client.run_command('uname')) |
| 115 | + |
| 116 | + [localhost] Linux |
| 117 | + |
| 118 | +Using standard input |
| 119 | +---------------------- |
| 120 | + |
| 121 | +Along with standard output and error, input is also available on the host output object. It can be used to send input to the remote host where required, for example password prompts or any other prompt requiring user input. |
| 122 | + |
| 123 | +The `stdin` channel is a file-like object that can be written to:: |
| 124 | + |
| 125 | + output = client.run_command('read') |
| 126 | + stdin = output['localhost'].stdin |
| 127 | + stdin.write("writing to stdin\\n") |
| 128 | + stdin.flush() |
| 129 | + for line in output['localhost'].stdout: |
| 130 | + print(line) |
| 131 | + |
| 132 | +Output:: |
| 133 | + |
| 134 | + writing to stdin |
| 135 | + |
| 136 | +Errors and Exceptions |
| 137 | +----------------------- |
| 138 | + |
| 139 | +By default, `parallel-ssh` will fail early on any errors connecting to hosts, whether that be connection errors such as DNS resolution failure or unreachable host, SSH authentication failures or any other errors. |
| 140 | + |
| 141 | +Alternatively, the `stop_on_errors` flag is provided to tell the client to go ahead and attempt the command(s) anyway and return output for all hosts, including the exception on any hosts that failed:: |
| 142 | + |
| 143 | + output = client.run_command('whoami', stop_on_errors=False) |
| 144 | + |
| 145 | +With this flag, the `exception` attribute will contain the exception on any failed hosts, or `None`:: |
| 146 | + |
| 147 | + client.join(output) |
| 148 | + for host, host_output in output.items(): |
| 149 | + print("Host %s: exit code %s, exception %s" % ( |
| 150 | + host, host_output.exit_code, host_output.exception)) |
| 151 | + |
| 152 | +Output:: |
| 153 | + |
| 154 | + host1: 0, None |
| 155 | + host2: None, AuthenticationException <..> |
| 156 | + |
| 157 | +Possible exceptions can be found in :mod:`pssh.exceptions` module. |
0 commit comments