Как да отговаряте автоматично на подкани с python fabric?

Искам да изпълня команда, която ме подканва да въведа да/не или да/н или каквото и да е друго. Ако просто изпълня командата local("my_command"), тогава тя спира и ме пита за въвеждане. Когато напиша това, което е необходимо, скриптът продължава да работи. Как мога автоматично да отговоря на подканата?


person aemdy    schedule 07.05.2012    source източник
comment
@aemdy бихте ли променили отговора, така че да бъде този, предложен от Timothée Jeannin. Виждал съм няколко други въпроса като този и избраният в момента отговор е остарял. Това би улеснило хората да получат правилния отговор :).   -  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

Забележка: този отговор е на няколко години и междувременно тъканта има (интересно подобно изглеждащо) изпълнение на това. Вижте отговора от @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
Благодаря, Морган, съгласен съм. Предложих нещо в списъка с тъкани, но досега не получих отговор и в крайна сметка написах 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 код: 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--dealing-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

За да разширите малко отличния отговор на Timothée, ето кодът, който 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

run("да | моята_команда");

person MrBrightside    schedule 29.05.2015