Remote Commands via Fabric Part 1 - Hello Linux.org!

E

Eric Hansen

Guest
Before I mentioned tips on creating an easier-to-manage server farm involving a central server to manage SSH connections and restricting the other servers to one IP. If you only have a few servers (< 10) then its fairly easy (granted slightly time consuming and majorly repetitive). But what if I told you there was a way to turn a 20-minute assignment into 20 seconds?

Introducing Fabric
Fabric is a Python module and command line tool to execute SSH commands on numerous machines for you (as close to automation as you can get besides hardcoding a shell script). While it is very powerful and dynamic I’ll only be covering the basics here. I’ll cover more about Fabric in the future though as it is a very beneficial tool to have.

Requirements
Ah yes, the dreaded requirements ;). While there isn’t many (Python 2.5 or higher [I use 2.7.5] and pip), setting this up is outside the scope of this guide. When you have pip installed just run the following command:
Code:
pip install fabric
Boom, you got Fabric installed and you only need it installed on one machine!

Hello Linux.org!
Lets do a small test run first to make sure Fabric runs okay. Create a new file called fabfile.py (requirement as well else it won’t work) and put this code in it, then save:
Code:
def hello():
    print "hello linux.org!"
Now just run “fab hello” from the command prompt and you should get the message “hello linux.org!” back:
Code:
(fab):02:58 PM: (~/git/fab) [email protected]$ fab hello

hello linux.org!

Done.
Running Remote Commands
This won’t have any error checking to it (though it is easy to do) as this guide is meant to basically speed run you through this tool. However, now we’ll get into some of the fun aspects of Fabric: remote execution.

First we need to know what hosts we are going to connect to. For the sake of this guide I’ll just be connecting to my local server 192.168.0.112, but hostnames can work too. If you have a SSH config file set up with various host translations/settings/etc… you can also pass “--ssh-config-path=(path)” to fab when you run the method (i.e.: if your SSH config is located at /home/me/.ssh/config then when you run fab it would be fab --ssh-config-path=/home/me/.ssh/config …).

Required Imports
While this isn’t a safe (or sane) way to program in Python, for the sake of development and ease we’ll just import everything found in the Fabric API with a simple line:
Code:
from fabric.api import *
This will import all of the methods, variables, etc… needed.

Specifying Hosts
Like I said I’ll be performing these on my home server 192.168.0.112. Replace that with the IPs and/or hostnames of your machines (side note: there are easy ways to go about this, and also keep in mind Fabric uses SSH) but set this just below the above line:
Code:
env.hosts = ['192.168.0.112']
Run Remote Commands
Our “hello” method unfortunately will not work for us here. The reason being is that Fabric will think you’re just wanting to run the method on the local machine since you’re not specifically telling it to run anything. That is where the API-builtin “run” method comes in.

When called it will run any command given as the parameter on the host(s) specified. So, to make it easy, we will simply echo out our hello statement. Replace the above def hello() lines with this:
Code:
def echo():
    run("echo -n 'hello linux.org'")
Now save.

Running Fabric
For the most part you shouldn’t have any issues. However, I ran into a snag personally that might affect you too.

Fabric uses the user’s .ssh directory for public keys. This means that if Fabric can’t find a key for the specific host it’ll error out (i.e.: if you use a password instead of keyfile for authentication). While for many reasons its looked down upon for my home server I chose to not use keyfiles simply out of laziness (plus its not publicly accessible). If you’re like me then you’ll have to add the argument “-a” after “fab”. Here’s what it looks like now:
Code:
(fab):03:11 PM: (~/git/fab) [email protected]$ fab -a echo

[192.168.0.112] Executing task 'echo'
[192.168.0.112] run: echo -n 'hello linux.org'
[192.168.0.112] Login password for 'eric':
[192.168.0.112] out: hello linux.org

Done.

Disconnecting from 192.168.0.112... done.
Pretty cool, huh? Now, for a bit of fun I’ll show you what it looks like when done on multiple servers (2 in this case):
Code:
(fab):03:12 PM: (~/git/fab) [email protected]$ fab -a echo

[192.168.0.112] Executing task 'echo'
[192.168.0.112] run: echo -n 'hello linux.org'
[192.168.0.112] Login password for 'eric':
[192.168.0.112] out: hello linux.org
[[email protected]] Executing task 'echo'
[[email protected]] run: echo -n 'hello linux.org'
[[email protected]] Login password for ‘eric':
[[email protected]] out: hello linux.org

Done.

Disconnecting from [email protected] done.

Disconnecting from 192.168.0.112... done.
If you want to specify the user in the host use “[email protected]” in front of the host.

Complete Code
Here’s the complete code used to make the above happen:
Code:
from fabric.api import *

env.hosts = ['192.168.0.112','[email protected]’]

def echo():
    run("echo -n 'hello linux.org'")
The method “echo” can be anything you want, just make note that its what you need to pass to Fabric when you run the script. You can even make various methods do specific actions and call them, pass arguments to methods, etc… All of which will be covered later.
 

Attachments





Members online


Latest posts

Top