Quickstart¶
First, make sure that parallel-ssh
is installed.
Run a command on hosts in parallel¶
The most basic usage of parallel-ssh
is, unsurprisingly, to run a command on multiple hosts in parallel.
A complete example is shown below.
Examples all assume a valid key is available on a running SSH agent. See Programmatic Private Key Authentication for authenticating without an SSH agent.
Complete Example¶
Host list can contain identical hosts. Commands are executed concurrently on every host given to the client regardless, up to pool size.
from pssh.clients import ParallelSSHClient
hosts = ['localhost', 'localhost', 'localhost', 'localhost']
client = ParallelSSHClient(hosts)
cmd = 'uname'
output = client.run_command(cmd)
for host_out in output:
for line in host_out.stdout:
print(line)
- Output:
Linux Linux Linux Linux
Single Host Client¶
parallel-ssh
has a fully featured, asynchronous single host client that it uses for all its parallel commands.
Users that do not need the parallel capabilities can use the single host client for a simpler way to run asynchronous non-blocking commands on a remote host.
from pssh.clients import SSHClient
host = 'localhost'
cmd = 'uname'
client = SSHClient(host)
host_out = client.run_command(cmd)
for line in host_out.stdout:
print(line)
- Output::
Linux
Step by Step¶
Make a list or other iterable of the hosts to run on:
from pssh.clients import ParallelSSHClient
hosts = ['host1', 'host2', 'host3', 'host4']
Where host1
to host4
are valid host names. IP addresses may also be used.
Create a client for these hosts:
client = ParallelSSHClient(hosts)
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.
Now one or more commands can be run via the client:
output = client.run_command('uname')
When the call to run_command
returns, the remote commands are already executing in parallel.
Run Command Output¶
Standard Output¶
Standard output, aka stdout
, for a given HostOutput
object.
for line in host_out.stdout:
print(line)
Output: | <line by line output>
<line by line output>
<..>
|
---|
Iterating over stdout
will only end when the remote command has finished unless interrupted.
The read_timeout
keyword argument to run_command
may be used to cause reading to timeout if no output is received after the given number of seconds - see join and output timeouts.
stdout
is a generator. To retrieve all of stdout can wrap it with list, per below.
stdout = list(host_out.stdout)
All hosts iteration¶
Of course, iterating over all hosts can also be done the same way.
for host_output in output:
for line in host_output.stdout:
print("Host [%s] - %s" % (host, line))
Complete Example¶
from pssh.clients import ParallelSSHClient
client = ParallelSSHClient(['localhost', 'localhost'])
output = client.run_command('whoami')
client.join()
for host_output in output:
hostname = host_output.host
stdout = list(host_output.stdout)
print("Host %s: exit code %s, output %s" % (
hostname, host_output.exit_code, stdout))
Output: | localhost: exit code 0, stdout ['<username>']
localhost: exit code 0, stdout ['<username>']
|
---|
New in 1.10.0
Exit codes¶
Exit codes are available on the host output object as a dynamic property. Exit code will be None
if not available, or the exit code as reported by channel.
First, ensure that all commands have finished by either joining on the output object or gathering all output, then iterate over all host’s output to print their exit codes.
client.join(output)
for host_output in output:
print("Host %s exit code: %s" % (host_output.host, host_output.exit_code))
As of 1.11.0
, client.join
is not required as long as output has been gathered.
for host_out in output:
for line in host_out.stdout:
print(line)
print(host_out.exit_code)
See also
pssh.output.HostOutput
- Host output class documentation.
Authentication¶
By default parallel-ssh
will use an available SSH agent’s credentials to login to hosts via public key authentication.
User/Password authentication¶
User/password authentication can be used by providing user name and password credentials:
client = ParallelSSHClient(hosts, user='my_user', password='my_pass')
Note
On Posix platforms, user name defaults to the current user if not provided.
On Windows, user name is required.
Programmatic Private Key authentication¶
It is also possible to programmatically provide a private key for authentication.
from pssh.clients import ParallelSSHClient
client = ParallelSSHClient(hosts, pkey='my_pkey')
Where my_pkey
is a private key file in the current directory.
To use files under a user’s .ssh
directory:
client = ParallelSSHClient(hosts, pkey='~/.ssh/my_pkey')
Output for Last Executed Commands¶
Output for last executed commands can be retrieved by get_last_output
:
client.run_command('uname')
output = client.get_last_output()
for host_output in output:
for line in host_output.stdout:
print(line)
This function can also be used to retrieve output for previously executed commands in the case where output object was not stored or is no longer available.
New in 1.2.0
Host Logger¶
There is a built in host logger that can be enabled to automatically log standard output from remote hosts. This requires the consume_output=True
flag on join
.
The helper function pssh.utils.enable_host_logger()
will enable host logging to standard output, for example:
from pssh.utils import enable_host_logger
enable_host_logger()
client.run_command('uname')
client.join(consume_output=True)
Output: | [localhost] Linux
|
---|
Using standard input¶
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.
The stdin
attribute on HostOutput
is a file-like object giving access to the remote stdin channel that can be written to:
output = client.run_command('read line; echo $line')
host_output = output[0]
stdin = host_output.stdin
stdin.write("writing to stdin\n")
stdin.flush()
for line in host_output.stdout:
print(line)
Output: | writing to stdin
|
---|
Errors and Exceptions¶
By default, parallel-ssh
will raise exception 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.
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:
output = client.run_command('whoami', stop_on_errors=False)
With this flag, the exception
output attribute will contain the exception on any failed hosts, or None
:
client.join(output)
for host_output in output:
host = host_output.host
print("Host %s: exit code %s, exception %s" % (
host, host_output.exit_code, host_output.exception))
Output: | Host host1: exit code 0, exception None
Host host2: exit code None, exception AuthenticationError <..>
|
---|
See also
Exceptions raised by the library can be found in the pssh.exceptions
module and in API documentation.