[Django]-Running fabric script locally

80👍

Yes, you can run fab locally by using method local instead of run. What I do typically is have methods for setting up the environment, and call these methods first before calling the actual task. Let me illustrate this with an example for your specific question

fabfile.py

    from fabric.operations import local as lrun, run
    from fabric.api import task
    from fabric.state import env

    @task
    def localhost():
        env.run = lrun
        env.hosts = ['localhost']

    @task
    def remote():
        env.run = run
        env.hosts = ['some.remote.host']

    @task
    def install():
        env.run('deploymentcmd')

And based on the environment, you can do the following

Install on localhost:

    fab localhost install

Install on remote machine:

    fab remote install

7👍

I am using another trick for executing remote task locally:

from fabric.api import run, sudo, local
from contextlib import contextmanager

@contextmanager
def locally():
    global run
    global sudo
    global local
    _run, _sudo = run, sudo
    run = sudo = local
    yield
    run, sudo = _run, _sudo

def local_task():
    with locally():
        run("ls -la")
👤xuhcc

4👍

Slightly less elegant than Varun’s answer, but maybe more practical by defaulting to run on the local machine unless another environment selector is given.

from fabric.api import *

# default to running on localhost
env.hosts = ["localhost"]

DEPLOYMENT_PATH = "/some/path/{}/"

def local_or_remote(*args, **kwargs):
    func = local if env.host == "localhost" else run
    return func(*args, **kwargs)


@task
def live():
    """
    Select live environment
    """
    env.hosts = ["host1", "host2"]
    env.path = DEPLOYMENT_PATH.format("live")


@task
def beta():
    """
    Select beta environment
    """
    env.hosts = ["host1", "host2"]
    env.path = DEPLOYMENT_PATH.format("beta")


@task
def host_info():
    local_or_remote("uname -a")

Then run locally as:

fab host_info

or remotely with:

fab live host_info

PS. Here is the Github issue on this topic.

3👍

First, make sure you can ssh into your localhost without a password:

$ ssh-copy-id localhost

And then just run it as you said, with the -H localhost command line option

2👍

You can run ssh server on your local machine to be able to ssh to localhost. And then just run scripts with “-H localhost”. Works perfectly for me.

0👍

A modified version of Varun’s answer that takes into account local not capturing stdout/stderr. Without specifying capture=True you would not be able to get results from local.

from fabric.operations import local, run
from fabric.api import task
from fabric.state import env

def local_run(*args):
    return local(args[0], capture=True)

@task
def localhost():
    env.run = local_run
    env.hosts = ['localhost']

@task
def remote():
    env.run = run
    env.hosts = ['some.remote.host']

@task
def install():
    env.run('deploymentcmd')

Leave a comment