Как автоматически отвечать на запросы с помощью ткани Python?

Я хочу запустить команду, предлагающую мне ввести да / нет, да / нет или что-то еще. Если я просто запустил команду local("my_command"), она остановится и попросит меня ввести данные. Когда я печатаю то, что нужно, скрипт продолжает работать. Как я могу автоматически ответить на запрос?


person aemdy    schedule 07.05.2012    source источник
comment
@aemdy, не могли бы вы изменить ответ на тот, который предложил Тимоти Жаннин. Я видел еще несколько подобных вопросов, и выбранный на данный момент ответ устарел. Так людям было бы намного проще получить правильный ответ :).   -  person Breedly    schedule 05.02.2017


Ответы (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')
person Timothée Jeannin    schedule 19.08.2014
comment
Совершенно уверен, что это должен быть неофициально принятый ответ. - person MrDuk; 09.09.2015
comment
@aemdy Это действительно должен быть принятый ответ на данный момент, работает из коробки без проблем. - person Nathan Cox; 14.12.2015
comment
Совет: ключи словаря подсказок сопоставляются с помощью встроенной функции Fabric io._endswith. Если вы не можете понять, почему ваши шаблоны не совпадают, возможно, вы забыли поставить пробел в конце. Например, пароль UNIX: или Новый пароль: или Введите новый пароль еще раз: - person scottwed; 07.06.2016
comment
Я получаю NameError: global name 'settings' is not defined - person rofls; 28.07.2016
comment
Я изо всех сил пытаюсь понять, как я могу использовать это, чтобы сначала запустить последовательность действий и только затем ответить на приглашение. Там в любом случае? - person Shon; 18.08.2016
comment
Fabric использует .endswith для своей проверки, поэтому убедитесь, что вы включили завершающие пробелы в строке, которую вы используете в качестве ключа в словаре prompts. - person Christian Long; 21.11.2016
comment
Я обнаружил, что после '[Y / n]? ', нужно это или нет? - person Kingname; 12.12.2016
comment
Это работает с функцией local()? Я попробовал что-то простое, например with settings(prompts={'Continue? ': 'Y'}): local('read -p "Continue? " var', capture=True), и оно было заблокировано в командной строке. Обновление: похоже, что вход все еще был подключен к консоли :( - person haridsv; 17.05.2017
comment
Чтобы ответить на мой собственный вопрос сверху, похоже, что запросы обрабатываются в ssh io, а local - это просто простая оболочка поверх Popen, поэтому это не сработает. Думаю, нам нужно использовать pexpect. - person haridsv; 17.05.2017

Я использовал простые эхо-каналы, чтобы отвечать на запросы с помощью Fabric.

run('echo "yes\n"| my_command')
person Henri Siponen    schedule 07.05.2012
comment
Вы также можете использовать команду yes: run("yes | my_command") - person Bob Nadler; 29.07.2014
comment
Внимание к yes! - person benzkji; 07.02.2020

Примечание: этому ответу несколько лет, и в то же время в Fabric есть (что интересно) реализация этого. См. Ответ @ timothée-jeannin ниже.

См. https://stackoverflow.com/a/10007635/708221

pip install fexpect

from ilogue.fexpect import expect, expecting, run 

prompts = []
prompts += expect('What is your name?','John')
prompts += expect('Are you at stackoverflow?','Yes')

with expecting(prompts):
    run('my_command')

Fexpect добавляет ответ на запросы к ткани с использование pexpect

person Jasper van den Bosch    schedule 07.05.2012
comment
Классный проект, но было бы лучше, если бы он не полагался на размещение файла python на сервере. Нужно проверить это больше и посмотреть, могу ли я помочь. - person Morgan; 08.05.2012
comment
Спасибо, Морган, согласен. Я предложил кое-что из списка Fabric, но пока не получил ответа, и в итоге написал fexpect, что стоило мне меньше времени, чем изучение внутреннего устройства Fabric. - person Jasper van den Bosch; 08.05.2012
comment
Верно, я думаю, что видел это, но, возможно, не понял намерения. Я очень заинтересован в том, чтобы продвигать это дальше, и у меня был некоторый опыт работы с внутренними компонентами Fabric, а до того, как я нашел Fabric, это pxssh / pexpect. - person Morgan; 09.05.2012
comment
Хорошо, дайте мне знать, могу ли я чем-то помочь - person Jasper van den Bosch; 09.05.2012
comment
у меня это не работает: pastebin.com/vAPwVxaR code: pastebin.com/HFUJkb6J - person ; 24.11.2013
comment
Пожалуйста, опубликуйте это как новый вопрос и отправьте мне. Также, если возможно, включите свой код Python - person Jasper van den Bosch; 25.11.2013
comment
Ссылка на сообщение в блоге в настоящее время недоступна, ilogue.com продается ... Вот заархивированная страница: http://web.archive.org/web/20140624141333/http://ilogue.com/jasper/blog/fexpect-deal-with-prompts-in-fabric-with-pexpect/ - person FooF; 01.12.2015
comment
Очередная зависимость от мертвого проекта? Фу. - person Cerin; 22.06.2016
comment
Теперь у Fabric есть потрясающая встроенная поддержка для этого. Проверьте несколько комментариев, чтобы получить ответ из 31 балла. - person Breedly; 05.02.2017
comment
@Breedly Я добавил примечание к этому ответу в качестве предупреждения для посетителей - person Jasper van den Bosch; 05.02.2017

Чтобы немного расширить отличный ответ Тимоти, вот код, который 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

Fabric использует .endswith для своей проверки, поэтому убедитесь, что вы включили завершающие пробелы в строке, которую вы используете в качестве ключа в словаре prompts.

Например - предположим, вы пытаетесь автоматизировать приглашение тестовой базы данных Django.

Введите «да», если вы хотите попробовать удалить тестовую базу данных «test_my_app», или «нет» для отмены:

Все, что нам нужно, - это конец приглашения, чтобы оно было уникальным. Включите конечные пробелы.

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,
                  )
       )
person Christian Long    schedule 21.11.2016

В Fabric 2.1 это можно сделать с помощью пример автоответа, доступный через пакет вызова (зависимость от 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 НЕ необходим, но может быть важен, потому что делает поток более реалистичным. например если у вас было приглашение, ожидающее продолжения ответа да / нет, без него (pty=True) ваша команда все равно будет выполняться; кроме, ваш выбор / ввод (указанный response) не будет отображаться как набранный в качестве ответа, как можно было бы ожидать.
  2. pattern, указанный в Responder, часто может включать пробелы в конце строки, поэтому попробуйте добавить пробелы, если watcher не соответствует.
  3. Согласно примечанию, приведенному в конце документации наблюдателя:

    Аргумент шаблона для Responder обрабатывается как регулярное выражение, требующее большей осторожности (обратите внимание, как нам пришлось избегать квадратных скобок в приведенном выше примере), но также предоставляющее больше возможностей.

    Так что не забывайте экранировать (используя обратную косую черту) там, где это необходимо.

person slaw    schedule 29.06.2018

Помещая это как ответ, хотя это комментарий от @BobNadler

запустить ("да | моя_команда");

person MrBrightside    schedule 29.05.2015