我想在本地运行我的结构脚本,然后登录到我的服务器,切换用户进行部署,激活项目.virtualenv,这会将dir更改为项目并发出git pull.
def git_pull(): sudo('su deploy') # here i need to switch to the virtualenv run('git pull')
我通常使用virtualenvwrapper中的workon命令来源激活文件,postactivate文件将把我放在项目文件夹中.在这种情况下,似乎因为结构从shell内部运行,控制权交给了结构,所以我不能使用bash的源内置'$ source~/.virtualenv/myvenv/bin/activate'
任何人都有他们如何做到这一点的例子和解释?
作为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')
现在,你可以做我做的事情,这是kludgy但工作得很好*(这种用法假设你使用virtualenvwrapper - 你应该 - 但你可以轻松替换你提到的相当长的'源'电话, 如果不):
def task(): workon = 'workon myvenv && ' run(workon + 'git pull') run(workon + 'do other stuff, etc')
从1.0版开始,Fabric有一个使用这种技术的prefix
上下文管理器,所以你可以举例:
def task(): with prefix('workon myvenv'): run('git pull') run('do other stuff, etc')
*必然会出现这样的情况:使用该command1 && command2
方法可能会对您造成爆炸,例如command1
失败(command2
永远不会运行)或者command1
未正确转义并包含特殊shell字符等等.
我只是使用一个简单的包装函数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)
virtualenvwrapper
可以使这更简单
使用@ 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")
或部署您的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")
这是我使用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')