Question

Je veux lancer mon script tissu local, qui, à son tour, connectez-vous mon serveur, l'utilisateur du commutateur pour déployer, activer les projets .virtualenv, qui changera dir au projet et émettre un git pull.

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

J'utilise généralement la commande WorkOn de virtualenvwrapper quelles sources le fichier d'activation et le fichier postactivate me mettre dans le dossier du projet. Dans ce cas, il semble que parce que le tissu passe à l'intérieur coquille, le contrôle est de donner plus de tissu, donc je ne peux pas utiliser une source de bash intégré pour « $ source ~ / .virtualenv / myvenv / bin / activate »

Quelqu'un a un exemple et une explication de la façon dont ils l'ont fait?

Était-ce utile?

La solution

En ce moment, vous pouvez faire ce que je fais, qui est kludgy mais fonctionne parfaitement bien * (cette utilisation suppose que vous utilisez virtualenvwrapper - que vous devriez être - mais vous pouvez facilement remplacer dans le lieu plus « source » vous appelez mentionné, sinon):

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

, Tissu a depuis la version 1.0 a prefix contexte gestionnaire qui utilise cette technique de sorte que vous pouvez par exemple:

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

* Il y a forcément des cas où l'aide de l'approche command1 && command2 peut sauter sur vous, comme lorsque command1 échoue (command2 sera jamais à court) ou si command1 est pas correctement échappées et contient des caractères shell spéciaux, et ainsi de suite.

Autres conseils

En tant que mise à jour des prévisions de bitprophet: Avec Fabric 1.0, vous pouvez utiliser préfixe () et vos propres gestionnaires de contexte.

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')

Je suis juste en utilisant une simple fonction d'emballage virtualenv () qui peut être appelée au lieu de run (). Il n'utilise pas le gestionnaire de contexte cd, donc les chemins relatifs peuvent être utilisés.

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 peut faire un peu plus simple

  1. En utilisant l'approche @ nh2 (cette approche fonctionne aussi lors de l'utilisation local, mais seulement pour les installations virtualenvwrapper où workon est en $PATH, autrement dit - 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. Ou déployer votre fichier fab et exécuter ce local. Cette configuration vous permet d'activer la virtualenv pour les commandes locales ou distantes. Cette approche est puissante, car cela fonctionne autour de l'incapacité de local à exécuter en utilisant .bashrc 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")
    

Ceci est mon approche sur l'utilisation virtualenv avec des déploiements locaux.

Utilisation de la trajectoire () de tissu gestionnaire de contexte que vous pouvez exécuter pip ou python avec les binaires 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')

Merci à toutes les réponses postées et je voudrais ajouter un autre pour cela. Il y a un module, tissu virtualenv , qui peut fournir la fonction comme le même code :

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

tissu virtualenv utilise fabric.context_managers.prefix, ce qui pourrait être une bonne façon:)

Si vous souhaitez installer les paquets à l'environnement ou si vous voulez exécuter des commandes en fonction des packages que vous avez dans l'environnement, j'ai trouvé ce hack pour résoudre mon problème, au lieu d'écrire des méthodes complexes de tissu ou d'installer de nouveaux packages OS:

/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 cette façon, vous ne pourriez pas besoin d'activer l'environnement, mais vous pouvez exécuter des commandes dans l'environnement.

Voici le code pour un décorateur qui se traduira par l'utilisation de l'environnement virtuel pour tous les appels 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

puis d'utiliser le décorateur, notez l'ordre des décorateurs est important:

@task
@with_venv
def which_python():
  "Gets which python is being used"
  run("which python")

Cette approche a fonctionné pour moi, vous pouvez appliquer cela aussi.

from fabric.api import run 
# ... other code...
def install_pip_requirements():
    run("/bin/bash -l -c 'source venv/bin/activate' "
        "&& pip install -r requirements.txt "
        "&& /bin/bash -l -c 'deactivate'")

En supposant venv est votre répertoire env virtuel et ajouter cette méthode le cas échéant.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top