Как автоматически отвечать на запросы с помощью python fabric?
Я хочу запустить команду, которая предложит мне ввести да / нет или y/n или что-то еще. Если я просто запустите команду local("my_command")
затем он останавливается и просит меня ввести. Когда я набираю то, что нужно, скрипт продолжает работать. Как я могу автоматически ответить на приглашение?
6 ответов
Начиная с версии 1.9
В Fabric есть способ правильно управлять этим.
Раздел о приглашениях в документации Fabric говорит:
Словарь подсказок позволяет пользователям управлять интерактивными подсказками. Если ключ в словаре найден в стандартном потоке вывода команды, Fabric автоматически ответит соответствующим значением словаря.
Вы должны быть в состоянии заставить Fabric автоматически отвечать на запросы, как это:
with settings(prompts={'Do you want to continue [Y/n]? ': 'Y'}):
run('apt-get update')
run('apt-get upgrade')
Я использовал простые эхо-трубки для ответа на запросы с Fabric.
run('echo "yes\n"| my_command')
Примечание: этому ответу уже несколько лет, и в то же время фабрика имеет (интересно выглядящий) реализацию этого. Смотрите ответ @timothée-jeannin ниже.
pip install fexpect
from ilogue.fexpect import expect, expecting, run
prompts = []
prompts += expect('What is your name?','John')
prompts += expect('Are you at stackru?','Yes')
with expecting(prompts):
run('my_command')
Fexpect добавляет ответы на запросы к ткани с использованием pexpect
В Fabric 2.1 это можно сделать с помощью примера автоответчика, который доступен через пакет invoke (зависимость от Fabric 2.1):
>>> from invoke import Responder
>>> from fabric import Connection
>>> c = Connection('host')
>>> sudopass = Responder(
... pattern=r'\[sudo\] password:',
... response='mypassword\n',
... )
>>> c.run('sudo whoami', pty=True, watchers=[sudopass])
[sudo] password:
root
<Result cmd='sudo whoami' exited=0>
Обратите внимание, что это не ограничивается паролями sudo и может использоваться везде, где у вас есть шаблон для сопоставления и стандартный ответ (это может быть не пароль).
Есть пара советов:
pty=True
наверное всегда нужноpattern
указано вResponder
часто могут включать пробелы в конце строки, поэтому попробуйте добавить пробелы, когдаwatcher
не похожеСогласно примечанию, обсужденному в конце документов наблюдателя:
Аргумент шаблона для Responder рассматривается как регулярное выражение, требующее большей осторожности (обратите внимание, как мы должны были избегать наших квадратных скобок в приведенном выше примере), но также обеспечивающее большую мощность.
Итак, не забудьте убежать (используя обратную косую черту), где это необходимо.
Чтобы немного рассказать о превосходном ответе Тимоте, вот код, который Fabric использует при проверке prompts
толковый словарь.
def _get_prompt_response(self):
"""
Iterate through the request prompts dict and return the response and
original request if we find a match
"""
for tup in env.prompts.iteritems():
if _endswith(self.capture, tup[0]):
return tup
return None, None
Ткань использует .endswith
для его проверки, поэтому убедитесь, что вы включаете конечные пробелы в строке, которую вы используете в качестве ключа в prompts
толковый словарь.
Например - допустим, вы пытаетесь автоматизировать запрос тестовой базы данных Django
Введите 'yes', если вы хотите удалить тестовую базу данных 'test_my_app', или 'no', чтобы отменить:
Все, что нам нужно, - это конец подсказки, чтобы она была уникальной. Включите конечные пробелы.
django_test_database_prompt = "or 'no' to cancel: "
# won't work without this trailing space ^
with settings(
prompts={django_test_database_prompt : 'yes'}
):
run('%s %s' % (virtualenv_python_path,
test_runner_file_path,
)
)
Положив это как ответ, хотя это комментарий от @BobNadler
run ("yes | my_command");