run () / sudo () разумно увидит, что вы переходите на localhost, и вместо этого просто запустите local (). Вероятно, это необязательная вещь.
Комментарии Джеффа к IRC:
и да, я имею в виду, что всегда будут накладные расходы с ssh и прямыми трубами навскидку, я не думаю, что было бы ужасно сложно обновить run / sudo (особенно в master теперь, когда они были реорганизованы) для вызова / возврата local ( ) разумно, я не уверен, что мне бы хотелось, чтобы это полумагическое поведение в ядре (даже если оно отключено по умолчанию с возможностью его включения, хотя это могло бы помочь), но даже в этом случае это был бы интересный эксперимент. и если это так просто, как я думаю, я, честно говоря, не могу придумать вескую причину не делать этого (опять же, при условии, что это не поведение по умолчанию)
Первоначально представленный Ник Уэлч ( mackstann ) на 2009-11-11 в 01:39 вечера EST
Джеймс Пирсон (xiong.chiamiov) написал:
Как также упоминалось в irc, я обычно не запускаю ssh-сервер на настольном компьютере, поэтому на самом деле я не могу использовать ssh для localhost.
11 ноября 2009 г., 15:13 EST
Трэвис Свисгуд ( tswicegood ) написал:
Я только что реализовал нечто подобное сегодня вечером в виде новой функции fabric.operations под названием do
. Он смотрит на env.run_as
чтобы узнать, равно ли оно "local", и при этом переключается на метод local
вместо run
(или sudo
если sudo=True
передается как kwarg). Он также обрабатывает префикс локальных команд с помощью sudo
в случае, если они выполняются локально.
Это своего рода другой способ решения этой проблемы, который работает без изменения поведения run
или sudo
. Эти изменения доступны в моем репозитории .
11 января 2010 г., 12:22 EST
Morgan Goose ( goosemo ) опубликовал:
Я действительно не считаю это правдоподобным. Какой смысл бегать как местный. Одним из требований Fabric является запуск sshd на машине, удаленно или с обратной связью. Другая проблема заключается в том, что при изменении только local не учитываются put, get, rsync_project и другие, которые все еще нуждаются в ssh. Попытка реализовать их на самом деле вызовет больше проблем, поскольку теперь это касается преобразования fabfiles в bash.
13 марта 2011 г., 23:14 EDT
Джефф Форсьер (
Хотя я также не уверен на 100%, что это отличная идея, очевидно, что это то, в чем многие пользователи чувствуют потребность - еще один запрос был подан под номером 364 с другим объяснением варианта использования.
Я также добавил билет на пробный запуск, связанный с этим, потому что (я полагаю - если кто-либо из запрашивающих пользователей может проверить это, это было бы здорово) основным вариантом использования этой функции является тестирование / проверка Бег.
23.06.2011, 11:26 EDT
Как отмечалось в # 538, если мы когда-либо сможем полностью нормализовать три бегуна, чтобы их можно было использовать взаимозаменяемо, нам нужно убедиться, что экранирование оболочки работает последовательно для них. Прямо сейчас мы не используем экранирование оболочки local
, хотя это, по крайней мере, частично, потому что он не использует оболочку оболочки.
Если кто-то задается вопросом, «зачем кому-то это делать?», Ответ заключается в том, что если у вас есть конвейер развертывания, может быть полезно запустить один и тот же точный сценарий развертывания, независимо от того, в какой среде, вместо того, чтобы иметь специальный сценарий настройки для localhost по сравнению со всем остальным.
+1 за функцию
+1
+10
+1
+1
Чтобы задержать вас, вы можете просто убедиться, что у вас запущен сервер OpenSSH. Сначала выполните sudo apt-get install ssh
чтобы убедиться, что он установлен (даже если вы думаете, что это так). Затем выполните sudo service ssh start
| stop
| restart
мере необходимости. Узнал из этой ветки .
+1
Мой вариант использования прост: я хочу использовать один и тот же сценарий django-deploy для настройки экземпляров ec2 как с помощью cloud-init через CloudWatch (случай для запуска локальных команд), так и с использованием обычного fab deploy_django -H foo@bar
.
+1
Это было бы действительно полезно. Один из вариантов использования, который у меня есть, - это использование vagrant shell provisioner для настройки конкретной vm с использованием фабрики и без необходимости ssh localhost.
+1
Я был удивлен, что не увидел этого в Fabric.
К вашему сведению: реализация этой функции становится более сложной, если вы думаете о функциях структуры, таких как reboot()
.
+1
Уже должен быть частью ядра!
+1
Это было бы совершенно логично: с абстрактной точки зрения, local
- это просто частный случай run
, в котором не задействован механизм SSH.
Еще одна вещь, на которую стоит обратить внимание (возможно, очевидная): Fabric должна быть достаточно умной, чтобы решить, следует ли преобразовывать run
в local
ПОСЛЕ чтения / etc / hosts.
Я имею в виду: если у нас есть
env.host = [ 'mywebserver' ]
и в / etc / hosts у нас есть:
127.0.0.1 mywebserver
тогда любые вызовы run
должны быть вызовами local
.
Продвигая эту концепцию дальше, мы также должны рассматривать run
как локальный вызов, когда удаленный хост разрешает IP-адрес, назначенный сетевому интерфейсу локальной машины.
Например:
fabfile:
env.host = [ 'mywebserver' ]
/ etc / hosts:
192.168.1.1 mywebserver
ip addr
:
[...]
eth0:
inet 192.168.1.1
[...]
+1
+1: +1:
: +1:
+1
+1
Fabric 2 будет использовать pyinvoke / invoke, так что это должно быть довольно легко сделать там. Я бы дождался Fabric 2, чтобы не взломать способ сделать это.
: +1:
+1
: +1:
: +1: Пожалуйста, реализуйте это, тем более что компьютеры Mac не настроены автоматически для настройки туннелей SSH для удаленного доступа к серверу localhost.
+1
+1 :)
+1 пожалуйста
: +1:
: +1:
: +1:
Мы используем Fab для сборки пакетов debian, и это добавляет дополнительную сложность
ребята привет всем
я пытаюсь создать клон ткани с разницей:
Вы можете посмотреть, нужна ли вам эта функция
https://github.com/Friz-zy/factory
Возможно, мне что-то не хватает в этом обсуждении, но вот что я сделал, чтобы использовать тот же код с командой fab run
как на локальном, так и на удаленных машинах.
env.use_ssh_config = True
в свой файл fabfile.pyЭто не решит вашу проблему, если вы не используете ssh-сервер на своем локальном компьютере.
: +1:
+1
+1 Пожалуйста, внедрите эту функцию :)
+1
Может быть очень полезно для начальной загрузки образов Docker с использованием существующих скриптов Fabric. Эта функция позволит избежать установки SSH-сервера в контейнер, что противоречит лучшим практикам Docker.
+1
+1
+1
В дополнение к ответу, предоставленному @AntoniosHadji , вот полные инструкции по выполнению этой работы;
# Generate new SSH key for local usage
ssh-keygen -f ~/.ssh/id_rsa -N ''
# Add server keys to users known hosts (eliminates 'are you sure' messages);
ssh-keyscan -H localhost > ~/.ssh/known_hosts
# Allow user to ssh to itself
cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys
Собственно, это можно сделать с помощью кухни . Вам нужно изменить все run
выполнения, чтобы они ссылались на cuisine.run
функцию, что можно легко сделать с помощью импорта, и изменить режим на локальный:
from cuisine import run, mode_local
mode_local()
print run("echo Hello")
Отлично @cgarciaarano
Для простых случаев использования это работает для меня:
from fabric.api import run, local
# ...
# in task:
if env.host is None or env.host == 'localhost':
run = local
: +1:
Я хочу, чтобы мой fabfile запускался удаленно или локально, когда ssh не подходит. Это включает в себя локальные оболочки для get / put / exists и т. Д.
: +1: У меня есть fabfiles, которые запускаются как локально, так и удаленно, и в итоге я взломал свои собственные функции оболочки для run / local / get, чтобы справиться со всеми тонкими различиями, такими как захват вывода и обработка ошибок.
Что делать, если у вас есть ssh-соединение, выполняющее динамическую переадресацию портов и привязку к 127.0.0.2 (все еще технически localhost) на порту 2223. Я вижу, как это может вызвать проблемы, для этого сопоставление на localhost и разрешение на 127.0.0.1, а не также поддержка всего класса 127.0.0.0/8 может быть хорошей идеей для обработки.
@ blade2005 Да, весь диапазон 127 ._._. * указывает на ваш локальный хост (кроме 127.0.0.0 и 127.255.255.255), но когда вы фактически указываете на свой локальный хост, вы не будете использовать порт, верно?
Поэтому я считаю, что мы можем с уверенностью предположить, что 127.*.*.* == localhost
и ssh можно избежать, но 127.*.*.*:*
указывает на перенаправленный порт, и требуется ssh.
Честно говоря, эта функция, вероятно, имела бы больше смысла в качестве стороннего плагина, созданного на основе ткани, похожего на библиотеку кухни. Затем мы просто импортируем обернутые функции для run / get / put / etc, которые будут знать, нужно ли запускать локально или удаленно на основе переменной env. По крайней мере, таким образом, кто-нибудь мог бы запустить это, чтобы все могли использовать.
Я реализовал что-то локально, и это намного больше, чем просто переключение между локальным / запуском. Вы должны учитывать префиксы, измененные каталоги, пользователей sudo и т. Д.
Вкратце подумал об этом в контексте другого тикета, связанного с 2.0, и понял, что есть еще кое-что, кроме простого « run
становится перепривязкой local
»:
local
и run
или любого из put
/ get
своей сути становится проблематичной: операции с четко определенными «local» и «remote» теперь «концы» указывают локально.run
или sudo
поднимает DoesntMakeAnySenseError
"или что-то в этом роде.put
/ get
предположительно может просто превратиться в shutil.copy
или аналогичныйlocal
, по-видимому, не изменится (хотя при печати того, что происходит, вероятно, все же нужно, чтобы оно отличалось от того, что run-except-locally
имеет префикс ...?)prefix
, cd
т. Д., Требуют ответов на аналогичные вопросы.sudo
вообще потенциально огромен и, вероятно, требует дополнительных проверок безопасности.local
, что является еще одной возможностью. Хотя и небольшая, любые команды sudo
которые даже работают локально (т.е. одна из них развертывается в Linux и развертывается из нее), по-видимому, должны оставаться локальными привилегиями (например, apt
/ yum
и друзья, возня с файрволлом и т. д.).sudo
также (как отмечалось выше Джоном) необходимо расширить возможность настройки отдельных векторов конфигурации local-vs-remote, поскольку пользователь sudo, пароль и т. Д., Вероятно, будут различаться между двумя сторонами.localhost
просто будут переданы соответствующие значения. (Кроме того, в качестве специального подкласса Context
"для локального запуска удаленных вещей" он может делать и другие вещи, если это необходимо).@ max-arnold пробовал это в альфа-версии v2 и столкнулся с запутанными проблемами, чего и следовало ожидать на данный момент, поскольку - я еще не дошел до варианта использования этого конкретного билета, кроме обеспечения run
и local
имеют максимально похожие API.
На данный момент большая проблема заключается просто в природе и API объекта, привязанного к контексту задачи ( c
или ctx
или как там это называется) posarg. В настоящее время, и это опять же, не предполагается, что это будет окончательным, просто так все закончилось до сих пор:
Executor
, или Fab 2 - х FabExecutor
, когда нет хозяев нет, это invoke.Context
, который имеет run
, что выполняется локально и отсутствует local
;fabric.Connection
, run
запускается удаленно, а local
является перепривязкой run
Invoke. Требуется более конкретное мышление, в том числе рассмотрение вариантов использования здесь и в связанных тикетах. Беглый мозговой штурм:
patchwork
(урожденная contrib
) и / или invocations
(аналогичная версия Invoke), особенно потому, что она сообщает, сколько совместного использования кода они могут делать. Многие задачи и / или подпрограммы в этих типах кодовых баз могут захотеть запускаться локально или удаленно.@task
и / или kwargs на одну и ту же, где пользователь может заявить о своих ожиданиях (т.е. «Я действительно хочу получить контекст с возможностью удаленного доступа», «пожалуйста, никогда не давайте мне удаленный контекст» и т. д.)@task
/ Task
; Кодовые базы pure-Invoke будут просто использовать его @task
который всегда будет запускать получение ванильного значения Context
, в то время как задачи, созданные с помощью версии Fabric, по крайней мере, будут иметь возможность получить Connection
, если не требуется.ctx.run()
.@task
«Мне нужна только базовая, ванильный контекст», при том понимании, что кто-то с точки зрения вызова Fabric (или Fabric-подобной) имеет возможность предоставить эти задает Connection
вместо Context
.local
когда он не существует (код ожидания Fabric / Connection запускается через Invoke)run
когда вместо этого был предоставлен контекст с удаленным run
(код вызова / ожидания контекста запускается через Fabric)Connection('localhost').run('foo')
_не будет использовать SSH_, а будет действовать точно так же, как Connection('localhost').local('foo')
.ssh.localhost_becomes_subprocess = True
или что-то еще.)На данный момент я могу использовать только upload_template()
для локального рендеринга шаблона.
Конечно, это можно было сделать так:
#http://matthiaseisen.com/pp/patterns/p0198/
import os
import jinja2
def render(tpl_path, context):
path, filename = os.path.split(tpl_path)
return jinja2.Environment(
loader=jinja2.FileSystemLoader(path or './')
).get_template(filename).render(context)
Но почему бы не иметь возможность рендерить локально?
Основное использование этой функции в моем случае - развертывание конфигурации приложения на моем локальном компьютере для локального тестирования.
Предположим, у вас есть settings.py.j2
который отображается на целевом сервере при развертывании, и там он называется settings.py
и содержит только код Python, без jinja.
Теперь вы хотите протестировать локально, но локально еще нет settings.py
, потому что его нужно отрендерить из settings.py.j2
.
Таким образом, ваше приложение не может запуститься, и вам придется вручную создать отдельный settings.py
для локального тестирования.
Это очень утомительно, и должно быть легче.
Например, в Ansible я бы просто сказал задаче, что она будет использовать «локальное соединение», и она будет отображаться на локальном хосте, не пытаясь подключиться к нему по ssh.
Пока эта функция не будет доступна в Fabric, я, конечно, буду использовать вставленное выше решение, так как это всего лишь несколько строк кода. Хотя имхо должно быть проще. Я чувствую, что такая ткань должна облегчить мне задачу.
@fninja Я еще не портировал сам upload_template
, но я определенно согласен с тем, что он подпадает под это проблемное пространство. Вероятно, можно было бы справиться с этим, просто разделив этап рендеринга Jinja-wrapping и этап загрузки-выгрузки строки, особенно, поскольку последний уже существует в форме «передать FLO в put
». Например:
from StringIO import StringIO # too lazy to remember the newer path offhand
from somewhere.jinja_wrapper import render
from invoke import task
<strong i="9">@task</strong>
def render_settings(c):
rendered = render('settings.py.j2', {'template': 'params'})
c.put(StringIO(rendered), 'remote/path/to/settings.py')
Но, вероятно, все еще есть место для еще более короткого аналога с одной остановкой для upload_template
который был бы либо методом Connection
или подпрограммой, принимающей аргумент Connection
.
В любом случае, это вызывает больше вопросов относительно того, как именно относиться к такого рода вещам - например, объекты Context
вызова не имеют put
/ get
. Стоит ли их добавлять? Это имеет смысл для пользователей Fabric в контексте этого тикета (тогда upload_template
или w / e могут просто вызвать put
в любом случае), но для пользователей, использующих только Invoke, это странно. и бесполезная часть API.
+1, чтобы сделать это основной функцией
Крестовина от №1637. Просто идея:
from fabric import task, local
<strong i="6">@task</strong>
<strong i="7">@local</strong>
def build(ctx):
with ctx.cd('/project/dir'):
ctx.run('build > artifact.zip')
<strong i="8">@task</strong>
def deploy(conn):
build(local(conn))
with conn.cd('/remote/path'), local(conn).cd('/project/dir'):
conn.put(remote_path='build.zip', local_path='artifact.zip')
В основном local()
может действовать как декоратор / контекстный менеджер / функция и преобразовывать Connection
в Context
.
Еще один вариант использования, о котором я не думаю, что упоминал: создание библиотеки многоразовых функций. В моем случае это в основном команды git
. Я написал чрезмерно упрощенный dorun
который скрывает различия между параметрами функции run
и local
(в версии 1); какая функция выбрана, передается как параметр. Вот, например, git checkout
:
def git_checkout(branch, remote='origin', run=run):
"""Checkout a branch if necessary."""
if branch == git_current_branch(run=run):
return
elif branch in git_local_branches(run=run):
dorun('git checkout ' + branch, run=run)
else:
dorun('git checkout -t -b {0} {1}/{0}'.format(branch, remote), run=run)
def git_current_branch(run=run):
"""Get the current branch (aka HEAD)"""
output = dorun('git name-rev --name-only HEAD', run=run)
return output.strip()
def git_local_branches(run=run):
"""Get a list of local branches; assumes in repo directory."""
output = dorun('git branch --no-color', run=run)
branches = {l.strip().split(' ')[-1]
for l in output.strip().split('\n')}
return branches
Это выглядит так:
from fabric.api import run as run_remote, local as run_local
def dorun(*args, **kwargs):
"""Work around the fact that "local" and "run" are very different."""
kwargs.setdefault('run', run_remote)
run = kwargs.pop('run')
if run == run_local:
kwargs.setdefault('capture', True)
elif 'capture' in kwargs:
del kwargs['capture']
return run(*args, **kwargs)
Я понятия не имею, что происходит с sudo
и есть проблемы, с которыми я не могу легко справиться, например, расширение ~remoteuser
для создания пути.
Самый полезный комментарий
Если кто-то задается вопросом, «зачем кому-то это делать?», Ответ заключается в том, что если у вас есть конвейер развертывания, может быть полезно запустить один и тот же точный сценарий развертывания, независимо от того, в какой среде, вместо того, чтобы иметь специальный сценарий настройки для localhost по сравнению со всем остальным.