Activar un virtualenv a través de fabric como usuario de implementación


Quiero ejecutar mi script fabric localmente, que a su vez, iniciará sesión en mi servidor, cambiará de usuario para implementar, activará los proyectos .virtualenv, que cambiará dir al proyecto y emitirá un git pull.

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

Normalmente uso el comando workon de virtualenvwrapper que obtiene el archivo activate y el archivo postactivate me pondrá en la carpeta del proyecto. En este caso, parece que debido a que la tela se ejecuta desde dentro de la cáscara, el control es ceder a la tela, así que no puedo usar bash fuente integrada en 'source source ~/.virtualenv/myvenv/bin/activate'

¿Alguien tiene un ejemplo y una explicación de cómo han hecho esto?

Author: Flimm, 2009-07-25

8 answers

Ahora mismo, puedes hacer lo que yo hago, que es kludgy pero funciona perfectamente bien* (este uso asume que estás usando virtualenvwrapper which que deberías ser which pero puedes sustituirlo fácilmente en la llamada 'source' bastante más larga que mencionaste, si no):

def task():
    workon = 'workon myvenv && '
    run(workon + 'git pull')
    run(workon + 'do other stuff, etc')

Desde la versión 1.0, Fabric tiene un prefix context manager que utiliza esta técnica para que pueda, por ejemplo:

def task():
    with prefix('workon myvenv'):
        run('git pull')
        run('do other stuff, etc')

* Es probable que haya casos en los que el uso de la command1 && command2 enfoque puede explotar en usted, tales como cuando command1 falla (command2 nunca se ejecutará) o si command1 no está correctamente escapado y contiene caracteres especiales de shell, y así sucesivamente.

 94
Author: bitprophet,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-04-25 00:21:46

Como una actualización del pronóstico de bitprophet: Con Fabric 1.0 puede hacer uso de prefix() y sus propios gestores de contexto.

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')
 135
Author: nh2,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-01 12:45:46

Solo estoy usando una función de envoltura simple virtualenv() que se puede llamar en lugar de run(). No utiliza el administrador de contexto de CD, por lo que se pueden usar rutas relativas.

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)
 17
Author: ehc,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-08-04 07:48:49

virtualenvwrapper puede hacer esto un poco más simple

  1. Usando el enfoque de @nh2 (este enfoque también funciona cuando se usa local, pero solo para instalaciones virtualenvwrapper donde workon está en $PATH, en otras palabras Windows Windows)

    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")
    
  2. O implemente su archivo fab y ejecútelo localmente. Esta configuración le permite activar el virtualenv para comandos locales o remotos. Este enfoque es poderoso porque funciona alrededor de la incapacidad de local para ejecutarse .bashrc usando bash -l:

    @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")
    
 8
Author: Mr. Dave,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-02-18 16:38:21

Este es mi enfoque sobre el uso de virtualenv con implementaciones locales.

Usando el gestor de contexto path() de fabric puedes ejecutar pip o python con binarios de virtualenv.

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')
 7
Author: darklow,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-09-10 11:51:45

Gracias a todas las respuestas publicadas y me gustaría añadir una alternativa más para esto. Hay un módulo, fabric-virtualenv , que puede proporcionar la función como el mismo código:

>>> from fabvenv import virtualenv
>>> with virtualenv('/home/me/venv/'):
...     run('python foo')

Fabric-virtualenv hace uso de fabric.context_managers.prefix, que podría ser una buena manera:)

 4
Author: Drake Guan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-09-07 07:02:36

Aquí está el código para un decorador que resultará en el uso de Entorno Virtual para cualquier llamada run / sudo:

# This is the bash code to update the $PATH as activate does
UPDATE_PYTHON_PATH = r'PATH="{}:$PATH"'.format(VIRTUAL_ENV_BIN_DIR)

def with_venv(func, *args, **kwargs):
  "Use Virtual Environment for the command"

  def wrapped(*args, **kwargs):
    with prefix(UPDATE_PYTHON_PATH):
      return func(*args, **kwargs)

  wrapped.__name__ = func.__name__
  wrapped.__doc__ = func.__doc__
  return wrapped

Y luego para usar el decorador, tenga en cuenta que el orden de los decoradores es importante:

@task
@with_venv
def which_python():
  "Gets which python is being used"
  run("which python")
 0
Author: Matt Campbell,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-06-27 22:38:03

Si desea instalar los paquetes en el entorno o desea ejecutar comandos de acuerdo con los paquetes que tiene en el entorno, he encontrado este truco para resolver mi problema, en lugar de escribir métodos complejos de fabric o instalar nuevos paquetes de sistema operativo:

/path/to/virtualenv/bin/python manage.py migrate/runserver/makemigrations  # for running commands under virtualenv

local("/home/user/env/bin/python manage.py migrate")    # fabric command


/path/to/virtualenv/bin/pip install -r requirements.txt   # installing/upgrading virtualenv

local("/home/user/env/bin/pip install -r requirements.txt")  #  fabric command

De esta manera es posible que no necesite activar el entorno, pero puede ejecutar comandos bajo el entorno.

 0
Author: vikas0713,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-04-17 06:35:46