Как автоматически отвечать на запросы с помощью 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 ниже.

См. /questions/1204989/kak-zastavit-fabric-avtomaticheski-a-ne-interaktivno-vzaimodejstvovat-s-komandami-obolochki-obedinit-s-pexpect/1205013#1205013

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 и может использоваться везде, где у вас есть шаблон для сопоставления и стандартный ответ (это может быть не пароль).

Есть пара советов:

  1. pty=True наверное всегда нужно
  2. pattern указано в Responder часто могут включать пробелы в конце строки, поэтому попробуйте добавить пробелы, когда watcher не похоже
  3. Согласно примечанию, обсужденному в конце документов наблюдателя:

    Аргумент шаблона для 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");

Другие вопросы по тегам