Chcę uruchomić mój skrypt tkaniny lokalnie, co z kolei spowoduje zalogowanie się do mojego serwera, przełączenie użytkownika na wdrożenie, aktywację projektów .virtualenv, co spowoduje zmianę katalogu na projekt i wysłanie polecenia git pull.
def git_pull():
sudo('su deploy')
# here i need to switch to the virtualenv
run('git pull')
Zwykle używam polecenia workon z virtualenvwrapper, które pozyskuje plik aktywacyjny, a plik po aktywacji umieszcza mnie w folderze projektu. W tym przypadku wydaje się, że ponieważ tkanina działa z wnętrza powłoki, kontrola jest przekazywana do tkaniny, więc nie mogę użyć wbudowanego źródła basha do `` $ source ~ / .virtualenv / myvenv / bin / Activation ''
Czy ktoś ma przykład i wyjaśnienie, jak to zrobił?
python
virtualenv
fabric
automated-deploy
Thomas Schreiber
źródło
źródło
workon
jakoprefix
?Odpowiedzi:
W tej chwili możesz zrobić to, co ja, co jest niezdarne, ale działa doskonale * (to użycie zakłada, że używasz virtualenvwrapper - którym powinieneś - ale możesz łatwo zastąpić w dość dłuższym wywołaniu źródła, o którym wspomniałeś , Jeśli nie):
def task(): workon = 'workon myvenv && ' run(workon + 'git pull') run(workon + 'do other stuff, etc')
Od wersji 1.0 Fabric ma
prefix
menedżera kontekstu, który wykorzystuje tę technikę, dzięki czemu możesz na przykład:def task(): with prefix('workon myvenv'): run('git pull') run('do other stuff, etc')
* Z pewnością zdarzają się przypadki, w których użycie tego
command1 && command2
podejścia może wybuchnąć na tobie, na przykład, gdycommand1
zawiedzie (command2
nigdy nie zadziała) lub jeślicommand1
nie zostanie prawidłowo ucieczone i zawiera specjalne znaki powłoki, i tak dalej.źródło
workon
jest nieznanysh
. Jak możemy powiedzieć tkaninie, aby zamiast tego używała bash?source venv/bin/activate
. Jest to łatwiejsze i działa po wyjęciu z pudełka.workon
to dodatkowa zależność, a nawet jeśli jest zainstalowana, musisz ją dodać.bashrc
- zbyt skomplikowana dla wdrożeń w sieci szkieletowej.Jako aktualizacja prognozy bitprophet: w Fabric 1.0 możesz skorzystać z prefix () i własnych menedżerów kontekstu.
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')
źródło
source
jest nieznanysh
. Jak możemy powiedzieć tkaninie, aby zamiast tego używała bash?.
zamiastsource
cd()
, gdy jesteś całkowicie określający ścieżkę doactivate
wprefix()
?prefix()
wydaje się, że nie ma tam płyty CD - zobacz te dokumenty, które robią to samo. Chcemycd
tam, aby podczasyield
wykonywania innych poleceń (pip freeze
w moim przykładzie) te polecenia były względne w stosunku do tego katalogu.Po prostu używam prostej funkcji opakowującej virtualenv (), którą można wywołać zamiast run (). Nie używa menedżera kontekstu cd, więc można użyć ścieżek względnych.
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)
źródło
virtualenvwrapper
może to trochę uprościćKorzystanie z podejścia @ nh2 (podejście to działa również podczas używania
local
, ale tylko w przypadku instalacji virtualenvwrapper, w którychworkon
jest$PATH
, innymi słowy - 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")
Lub wdróż plik fab i uruchom go lokalnie. Ta konfiguracja pozwala aktywować virtualenv dla poleceń lokalnych lub zdalnych. To podejście jest potężne, ponieważ rozwiązuje problem
local
braku możliwości uruchomienia .bashrc przy użyciubash -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")
źródło
To jest moje podejście do korzystania
virtualenv
z lokalnych wdrożeń.Korzystając z menedżera kontekstu path () tkaniny, możesz uruchamiać
pip
lubpython
z plikami binarnymi z 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')
źródło
Dziękuję wszystkim odpowiedziom i chciałbym dodać jeszcze jedną alternatywę. Istnieje moduł fabric-virtualenv , który może pełnić funkcję w tym samym kodzie:
>>> from fabvenv import virtualenv >>> with virtualenv('/home/me/venv/'): ... run('python foo')
Fabric-virtualenv wykorzystuje
fabric.context_managers.prefix
, co może być dobrym sposobem :)źródło
Jeśli chcesz zainstalować pakiety w środowisku lub chcesz uruchamiać polecenia zgodnie z pakietami, które masz w środowisku, znalazłem ten hack, aby rozwiązać mój problem, zamiast pisać złożone metody tkaniny lub instalować nowe pakiety systemu operacyjnego:
/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
W ten sposób możesz nie potrzebować aktywować środowiska, ale możesz wykonywać polecenia w środowisku.
źródło
Oto kod dekoratora, który spowoduje użycie środowiska wirtualnego dla wszystkich wywołań 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
a następnie, aby użyć dekoratora, pamiętaj, że kolejność dekoratorów jest ważna:
@task @with_venv def which_python(): "Gets which python is being used" run("which python")
źródło
To podejście zadziałało dla mnie, możesz to również zastosować.
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'")
Zakładając, że
venv
jest to twój wirtualny katalog env i dodaj tę metodę w razie potrzeby.źródło