Fabric tutorial 1 – Take command of your network

This is a guide for installing and using Fabric on Ubuntu.
Tested versions:
Ubuntu 11.10
Fabric 1.4.1

Fabric is a Python tool and a library for combining Python with SSH.
The tool can be used to execute Python functions from the command line. It’s also
possible to execute shell commands over SSH with Fabric and by combining the Python functions
with the SSH, it’s possible to automate system administration tasks. (fabfile.org)

Why Fabric?
You can use Fabric as a tool for centralized configuration management. You can run administrative tasks
on all of your machines simultaneously. Fabric is fast and easy to install and start using since there’s
no configuration needed, just install and start adding tasks to your fabfile.

Fabric doesn’t require anything else on the remote systems but a working SSH server. So if you
can control a device with SSH, you can also control it with Fabric. This is why Fabric is such
an easy and nice tool to add to your sysadmin tools. If you prefer Ruby over Python, take a look at a
similiar tool called Capistrano.

In these tutorials I will go through the installation and all the basics you need to start using
Fabric efficietly.

The installation

The recommended way to install Fabric is by using pip. If you don’t have pip, install it first.
sudo apt-get -y install python-pip
sudo pip install fabric

If you encounter any errors make sure you have at least Python 2.6 and pip 0.8.1 or above.

Making your first fabfile

Fabric uses a Python file called fabfile.py to execute tasks. The fabfile should be in the same
directory where you run the Fabric tool. Let’s create a basic Hello World first. Use whatever
text editor you wish for creating and modifying your fabfile. Just remember to name it fabfile.py.
This is taken from fabfile.org:
fabfile.py

def hello():
    print("Hello World!")

That’s all. It doesn’t even use the Fabric API yet. It’s just a simple python function that can be
executed with Fabric.

Now let’s run it:
fab hello
Hello World!

Done.

You can list all your functions/tasks with:
fab -l
Available commands:

hello

This was still executed only on your local machine. But of course you’ll want to create tasks that are
run on remote devices. Let’s move on to remote tasks.

Running a command on remote hosts

You can just keep adding to your existing fabfile. We need to define some hosts that should run our tasks.
This will done in the fabfile by using environmental variable env.hosts. Now we also have to import
Fabric API. We’ll also add our username to the fabfile.

fabfile.py

from fabric.api import *

env.hosts=["10.10.10.10", "webserver.local"]
env.user="hng"

def hostname_check():    # hostname_check is just a task name, replace with anything
    run("hostname")

And we can run it with:
fab hostname_check

Now the hostname command was run on the remote machines defined in the env.hosts. The username hng
was used to connect to these machines and the output was printed back to you.

If you have different usernames on different hosts, you can use:

env.hosts=["simo@10.10.10.10", "webserver.local"]
env.user="hng"

Now simo username would be used on 10.10.10.10 and hng would be used on webserver.local.

Fabric will ask for your password when connecting to a remote host unless you define it on the fabfile.
Instead of defining it on the fabfile you should use public key authentication. Here’s how to do it in both
ways:

Password in the fabfile (not recommended)

env.password="your_password"

Public key authentication
ssh-keygen
press enter so the key goes to the default location
press enter to leave passphrase empty
press enter to confirm the empty passphrase
ssh-copy-id simo@10.10.10.10
ssh-copy-id hng@webserver.local

Now you can SSH to these remote hosts without a password. And Fabric won’t ask for a password.

Using parameters to run a command

We don’t want to write a separate task for each command. Instead let’s create a task with parameters.

fabfile.py

def command(cmd):
    run(cmd)

Now the cmd is replaced by whatever we decide when running the task.
fab command:hostname

This would run the hostname command on remote hosts. Another example:
fab command:"hostname -I"

Running a sudo command

Running sudo commands is almost as easy as running normal commands.

def sudo_command(cmd):
    sudo(cmd)
    # or
    sudo("apt-get update")

Run it with:
fab sudo_command:"apt-get install geany"

Now running this will cause remote host to ask for our sudo password. Fabric only asks for same password
once per run. But for full automation we need to get rid of it completely.
Public key authentication won’t help us here. Defining the password in the fabfile would prevent
this but there’s another way.

Removing sudo password prompt

We have to add a line to the remote hosts’ sudoers file or you can add a new file to sudoers.d with
this content:

%your_groupname ALL=(ALL) NOPASSWD: ALL

To modify sudoers file, you can use:
sudo visudo

Just add the line to the end of the file.

For example user hng belongs to hng group so it would be

%hng ALL=(ALL) NOPASSWD: ALL

Just for enabling this for a certain user, just use it without the %:

hng ALL=(ALL) NOPASSWD: ALL

This has to be done on all of your remote hosts. Exercise: create a fab task to do it on all hosts.

Now we can run sudo commands on remote hosts without password prompting.

Let’s make a task that installs a package.

def install(package):
    sudo("apt-get -y install %s" % package)

Notice the %s. It’s a normal Python way of placing variables to a string of text. This way we can
easily use parameters in our tasks. Another example with more parameters and two commands:

def install(package1,package2):
    sudo("apt-get update")
    sudo("apt-get -y install %s %s" % (package1,package2))

You can run it with:
fab install:geany,e3

This would update sourcelist and install geany and e3 to our remote hosts.

If you need to run commands on the machine with Fabric. Just replace “run” with “local”:

def local_cmd():
    local("echo fabtest >> test.log")

Parallel execution

Since Fabric version 1.3.0 it’s been possible to run Fabric tasks simultaneously on all remote hosts.
To do this you can just add @parallel above your tasks or define it in the env.vars like this:

env.parallel=True

by task:

@parallel
def pcmd(cmd):
    run(cmd)

Notice that you shouldn’t run parallel commands that require user input in the middle of execution as
it will mess up everything.

Now you’ve learned to run simple commands with Fabric on remote hosts, try using multiple commands on a single task to create more complex tasks. On my next post we’ll transfer files with Fabric and learn some basic error handling.

The complete tutorial fabfile here:
fabfile.py

from fabric.api import *

env.hosts=["simo@10.10.10.10", "webserver.local"]
env.user="hng"
#env.password="password"
#env.parallel=True

def hostname_check():
    run("hostname")

def command(cmd):
    run(cmd)

def sudo_command(cmd):
    sudo(cmd)

def install(package):
    sudo("apt-get -y install %s" % package)

def local_cmd():
    local("echo fabtest >> test.log")

@parallel
def pcmd(cmd):
    run(cmd)

Feel free to leave a comment if you have any questions or improvement suggestions.

Sources:
http://fabfile.org

14 responses to “Fabric tutorial 1 – Take command of your network

  1. k3z October 20, 2012 at 8:36 am

    Great tutorial, thanks.
    Help me a lot to start with fabric et fabtools.

  2. hack4geek January 10, 2013 at 10:37 am

    Wonderful tutorial short and crisp.

  3. Pingback: Fabfile for Puppet installations « awaseroot

  4. Pingback: Aikataulu – Linuxin keskitetty hallinta – ict4tn011-3 keväällä 2013 | Tero Karvinen

  5. Ajay September 25, 2013 at 8:18 pm

    Nice Tutorial. Thanks

  6. Priya October 18, 2013 at 2:11 pm

    How can I access fabfile.py from remote host?
    Could anyone help me please. Thanks inadvance

  7. Pingback: Aikataulu – Linuxin keskitetty hallinta – ict4tn011-4 syksyllä 2013 | Tero Karvinen

  8. Pingback: ▶ Fabric tutorial 1 – Take command of your network | awaseroot | xessam-dot-net :: Technology Blog

  9. helioit June 14, 2014 at 7:20 am

    Thanks so much ❤

  10. UmeshKumar September 3, 2014 at 11:11 am

    Short and sweet 🙂

  11. αντρικα θεματα October 16, 2014 at 12:41 am

    Πρώτη φορά ερευνώ το site σου και
    είμαι πολύ ενθουσιαμένος που έχει τόσο ενδιαφέροντα άρθρα.

  12. flopsy November 23, 2014 at 4:40 am

    Great Article. How can I store all the outputs to a file ?

  13. Pingback: Tuntimuistiinpanoja 30.11.16 Linuxin Keskittty Hallinta – Linux opiskelua

Leave a comment