Искам да изпълня команда, която ме подканва да въведа да/не или да/н или каквото и да е друго. Ако просто изпълня командата local("my_command")
, тогава тя спира и ме пита за въвеждане. Когато напиша това, което е необходимо, скриптът продължава да работи. Как мога автоматично да отговоря на подканата?
Как да отговаряте автоматично на подкани с python fabric?
Отговори (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')
NameError: global name 'settings' is not defined
- person rofls; 28.07.2016
.endswith
за своята проверка, така че се уверете, че сте включили крайни интервали в низа, който използвате като ключ в prompts
речника.
- person Christian Long; 21.11.2016
local()
? Опитах нещо просто, като with settings(prompts={'Continue? ': 'Y'}): local('read -p "Continue? " var', capture=True)
и то беше блокирано при подканата. Актуализация: Изглежда, че входът все още е бил свързан към конзолата :(
- person haridsv; 17.05.2017
local
е просто обвивка върху Popen
, така че това няма да работи. Предполагам, че трябва да използваме pexpect
.
- person haridsv; 17.05.2017
Използвал съм прости ехо тръби, за да отговарям на подкани с Fabric.
run('echo "yes\n"| my_command')
yes
: run("yes | my_command")
- person Bob Nadler; 29.07.2014
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
За да разширите малко отличния отговор на 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,
)
)
В 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 и може да се използва навсякъде, където имате шаблон за съвпадение и готов отговор (който може да не е парола).
Има няколко съвета:
pty=True
НЕ е необходимо, но може да е важно, защото прави потока да изглежда по-реалистичен. напр. ако сте имали подкана, очакваща отговор да/не, за да продължите, без него (pty=True
) вашата команда пак ще се изпълнява; освен, вашият избор/въведено (посочено отresponse
) няма да бъде показано във въведено като отговор, както може да се очакваpattern
, посочено вResponder
, често може да включва интервали в края на реда, така че опитайте да добавите интервали, когатоwatcher
изглежда не съвпада.Според бележката, обсъдена в края на документи за наблюдение:
Аргументът шаблон към Responder се третира като регулярен израз, изискващ повече внимание (обърнете внимание как трябваше да избегнем нашите квадратни скоби в горния пример), но предоставя и повече мощност.
Така че, не забравяйте да избягате (използвайки обратни наклонени черти), където е необходимо.
Поставянето на това като отговор, въпреки че е коментар от @BobNadler
run("да | моята_команда");