Using Fabric for SSH¶
Fabric is a library and command-line tool for streamlining the use of SSH for application deployment or systems administration tasks.
It provides a basic suite of operations for executing local or remote shell commands (normally or via sudo) and uploading/downloading files, as well as auxiliary functionality such as prompting the running user for input, or aborting execution.
fab
Command¶
Fabric provides a command line utility fab
, which reads its configuration
from a file named fabfile.py
in directory from which it is run. A typical
fabfile contains one or more functions to be executed on a group of remote
hosts.
The following example provides functions to check free disk space and host type, as well as defining a group of hosts on which to run:
1 2 3 4 5 6 7 | from fabric.api import run
def host_type():
run('uname -s')
def diskspace():
run('df')
|
Once a task is defined, it may be run on one or more servers, like so:
(sysadmin)$ fab -H newyork,seattle host_type
[newyork] run: uname -s
[newyork] out: Linux
[seattle] run: uname -s
[seattle] out: Linux
Done.
Disconnecting from newyork... done.
Disconnecting from seattle... done.
Rather than supplying hostnames on the command line, you can also define the
group of hosts on which tasks will be run with env.hosts
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | from fabric.api import run
from fabric.api import env
env.hosts = [
'newyork',
'seattle',
'localhost',
]
def host_type():
run('uname -s')
def diskspace():
run('df')
|
Now run fab
without a -H
argument:
(sysadmin)$ fab host_type
[newyork] run: uname -s
[newyork] out: Linux
[seattle] run: uname -s
[seattle] out: Linux
[localhost] run: uname -s
[localhost] out: Linux
Done.
Disconnecting from newyork... done.
Disconnecting from seattle... done.
Disconnecting from localhost... done.
Task arguments¶
It’s often useful to pass runtime parameters into your tasks, just as you might
during regular Python programming. Fabric has basic support for this using a
shell-compatible notation: <task name>:<arg>,<kwarg>=<value>,...
. It’s
contrived, but let’s extend the above example to say hello to you personally:
[1]
def hello(name="world"):
print("Hello %s!" % name)
By default, calling fab hello
will still behave as it did before; but now
we can personalize it:
(sysadmin)$ fab hello:name=Jeff
Hello Jeff!
Done.
Those already used to programming in Python might have guessed that this invocation behaves exactly the same way:
(sysadmin)$ fab hello:Jeff
Hello Jeff!
Done.
For the time being, your argument values will always show up in Python as strings and may require a bit of string manipulation for complex types such as lists. Future versions may add a typecasting system to make this easier.
Library Usage¶
In addition to use via the fab tool, Fabric’s components may be imported into other Python code, providing a Pythonic interface to the SSH protocol suite at a higher level than that provided by e.g. the ssh library (which Fabric itself uses.) [2]
Lab – Average Uptime¶
Consider the case where we want to collect average uptime from a group of hosts.
File labs/fabric/uptime.py
will get you started:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | '''
Lab - Average Uptime
Write a script that uses the Fabric library to poll a group of hosts for their
uptimes, and displays their average uptime for the user.
'''
from fabric import tasks
from fabric.api import run
from fabric.api import env
from fabric.network import disconnect_all
env.hosts = [
'newyork',
'seattle',
'localhost',
]
def uptime():
res = run('cat /proc/uptime')
#
# Now, examine the result and extract the average uptime
#
def main():
uts_dict = tasks.execute(uptime)
#
# Now, calculate average uptime...
#
disconnect_all() # Call this when you are done, or get an ugly exception!
if __name__ == '__main__':
main()
|
Footnotes
[1] | http://docs.fabfile.org/en/1.4.2/tutorial.html#task-arguments |
[2] | http://stackoverflow.com/a/8166050 |