通过fabric作为部署用户激活virtualenv

Tho*_*ber 128 python automated-deploy virtualenv fabric

我想在本地运行我的结构脚本,然后登录到我的服务器,切换用户进行部署,激活项目.virtualenv,这会将dir更改为项目并发出git pull.

def git_pull():
    sudo('su deploy')
    # here i need to switch to the virtualenv
    run('git pull')
Run Code Online (Sandbox Code Playgroud)

我通常使用virtualenvwrapper中的workon命令来源激活文件,postactivate文件将把我放在项目文件夹中.在这种情况下,似乎因为结构从shell内部运行,控制权交给了结构,所以我不能使用bash的源内置'$ source~/.virtualenv/myvenv/bin/activate'

任何人都有他们如何做到这一点的例子和解释?

nh2*_*nh2 138

作为bitprophet预测的更新:使用Fabric 1.0,您可以使用prefix()和您自己的上下文管理器.

from __future__ import with_statement
from fabric.api import *
from contextlib import contextmanager as _contextmanager

env.hosts = ['servername']
env.user = 'deploy'
env.keyfile = ['$HOME/.ssh/deploy_rsa']
env.directory = '/path/to/virtualenvs/project'
env.activate = 'source /path/to/virtualenvs/project/bin/activate'

@_contextmanager
def virtualenv():
    with cd(env.directory):
        with prefix(env.activate):
            yield

def deploy():
    with virtualenv():
        run('pip freeze')
Run Code Online (Sandbox Code Playgroud)

  • 见http://readthedocs.org/docs/fabric/latest/api/core/context_managers.html (5认同)
  • 但是`source`是不知道的`sh`.我们如何告诉面料使用bash呢? (5认同)
  • 如何才能激活**本地**virtualenv? (3认同)
  • @PierredeLESPINAY你可以使用`.`而不是`source` (2认同)

bit*_*het 95

现在,你可以做我做的事情,这是kludgy但工作得很好*(这种用法假设你使用virtualenvwrapper - 你应该 - 但你可以轻松替换你提到的相当长的'源'电话, 如果不):

def task():
    workon = 'workon myvenv && '
    run(workon + 'git pull')
    run(workon + 'do other stuff, etc')
Run Code Online (Sandbox Code Playgroud)

从1.0版开始,Fabric有一个使用这种技术的prefix上下文管理器,所以你可以举例:

def task():
    with prefix('workon myvenv'):
        run('git pull')
        run('do other stuff, etc')
Run Code Online (Sandbox Code Playgroud)

*必然会出现这样的情况:使用该command1 && command2方法可能会对您造成爆炸,例如command1失败(command2永远不会运行)或者command1未正确转义并包含特殊shell字符等等.

  • 恕我直言你应该使用`source venv/bin/activate`.它更容易,开箱即用.`workon`是一个额外的依赖项,即使它已经安装,你必须在`.bashrc`中添加它 - 对于结构部署来说太复杂了. (17认同)
  • 但``work`在`sh`中是未知的.我们如何告诉面料使用bash呢? (7认同)

小智 17

我只是使用一个简单的包装函数virtualenv(),可以调用而不是run().它不使用cd上下文管理器,因此可以使用相对路径.

def virtualenv(command):
    """
    Run a command in the virtualenv. This prefixes the command with the source
    command.
    Usage:
        virtualenv('pip install django')
    """
    source = 'source %(project_directory)s/bin/activate && ' % env
    run(source + command)
Run Code Online (Sandbox Code Playgroud)


Dav*_*ave 8

virtualenvwrapper 可以使这更简单

  1. 使用@ NH2的方法(当使用这种方法也适用local,但仅限于virtualenvwrapper安装场合workon是$PATH,换句话说-视窗)

    from contextlib import contextmanager
    from fabric.api import prefix
    
    @contextmanager
    def virtualenv():
        with prefix("workon env1"):
            yield
    
    def deploy():
        with virtualenv():
            run("pip freeze > requirements.txt")
    
    Run Code Online (Sandbox Code Playgroud)
  2. 或部署您的fab文件并在本地运行.此设置允许您激活本地或远程命令的virtualenv.这种方法很强大,因为它local无法使用bash -l以下命令运行.bashrc :

    @contextmanager
    def local_prefix(shell, prefix):
        def local_call(command):
            return local("%(sh)s \"%(pre)s && %(cmd)s\"" % 
                {"sh": shell, "pre": prefix, "cmd": command})
        yield local_prefix
    
    def write_requirements(shell="/bin/bash -lic", env="env1"):
        with local_prefix(shell, "workon %s" % env) as local:
            local("pip freeze > requirements.txt")
    
    write_requirements()  # locally
    run("fab write_requirements")
    
    Run Code Online (Sandbox Code Playgroud)


dar*_*low 7

这是我使用virtualenv本地部署的方法.

使用fabric的path()上下文管理器,您可以运行virtualenv pip或python使用二进制文件.

from fabric.api import lcd, local, path

project_dir = '/www/my_project/sms/'
env_bin_dir = project_dir + '../env/bin/'

def deploy():
    with lcd(project_dir):
        local('git pull origin')
        local('git checkout -f')
        with path(env_bin_dir, behavior='prepend'):
            local('pip freeze')
            local('pip install -r requirements/staging.txt')
            local('./manage.py migrate') # Django related

            # Note: previous line is the same as:
            local('python manage.py migrate')

            # Using next line, you can make sure that python 
            # from virtualenv directory is used:
            local('which python')
Run Code Online (Sandbox Code Playgroud)