I would like to send a remote command to multiple hosts using the Python Fabric library. The following code works as long as all hosts are available
#!/usr/bin/python3
import fabric
group = fabric.ThreadingGroup('boss1', 'boss2')
results = group.run('uname -a', hide=True, timeout=5)
for _connection, _result in results.items():
print(f'{_connection.host}: {_result.stdout.strip()}')
If one of the hosts is unavailable I get a timeout error such as the following
fabric.exceptions.GroupException: {<Connection host=boss1 user=ec2-user>: TimeoutError(60, 'Operation timed out'), <Connection host=boss2 user=ec2-user>: <Result cmd='uname -a' exited=0>}
I would (1) like to reduce the timeout to 5 seconds (as is specified in group.run()
) and (2) isolate the error to only the bad host and return information from the successful one(s).
I have found documentation about connection_timeout
, but only group.run()
seems to accept a timeout
keyword and it does not reduce from 60 seconds.
I have also found documentation about a skip_bad_hosts
keyword but cannot insert it into my code without a runtime error.
What is the best way to skip over an error on one system and return results from the others?
Python 3, Fabric 3
I would like to send a remote command to multiple hosts using the Python Fabric library. The following code works as long as all hosts are available
#!/usr/bin/python3
import fabric
group = fabric.ThreadingGroup('boss1', 'boss2')
results = group.run('uname -a', hide=True, timeout=5)
for _connection, _result in results.items():
print(f'{_connection.host}: {_result.stdout.strip()}')
If one of the hosts is unavailable I get a timeout error such as the following
fabric.exceptions.GroupException: {<Connection host=boss1 user=ec2-user>: TimeoutError(60, 'Operation timed out'), <Connection host=boss2 user=ec2-user>: <Result cmd='uname -a' exited=0>}
I would (1) like to reduce the timeout to 5 seconds (as is specified in group.run()
) and (2) isolate the error to only the bad host and return information from the successful one(s).
I have found documentation about connection_timeout
, but only group.run()
seems to accept a timeout
keyword and it does not reduce from 60 seconds.
I have also found documentation about a skip_bad_hosts
keyword but cannot insert it into my code without a runtime error.
What is the best way to skip over an error on one system and return results from the others?
Python 3, Fabric 3
Share Improve this question asked yesterday shepstershepster 5091 gold badge5 silver badges17 bronze badges 1 |1 Answer
Reset to default 0The timeout needs to be specified in .ThreadingGroup()
(with a different parameter name) and if you capture the exception you can reveal which commands were successful or not.
#!/usr/bin/python3
import fabric
group = fabric.ThreadingGroup('boss1', 'boss2', connect_timeout=5)
try:
results = group.run('uname -nsr', hide=True)
except fabric.exceptions.GroupException as err:
results = err.result
for _connection, _result in results.items():
if hasattr(_result, 'stdout'):
print(f'{_connection.host}: {_result.stdout.strip()}')
else:
print(f'{_connection.host}: {_result}')
Sample output:
boss1: timed out
boss2: Linux boss2 4.14.355-275.582.amzn2.x86_64
fabric
is a thin wrapper around paramiko and invoke, so it doesn't handle the timeouts on its own. Youprobably need to create afabric.Connection
and specify theconnection_timeout
. – Tim Roberts Commented yesterday