如何使用python fabric自动回答提示?

时间:2012-05-07 08:40:34

标签: python command-prompt fabric

我想运行一个命令,提示我输入yes / no或y / n或者其他什么。如果我只是运行命令local("my_command"),那么它会停止并要求我输入。当我输入所需内容时,脚本继续工作。如何自动响应提示?

6 个答案:

答案 0 :(得分:44)

从版本1.9开始,Fabric提供了一种正确管理方法。

Fabric文档中的section about Prompts说:

  

提示词典允许用户控制交互式提示。如果   字典中的键可以在命令的标准输出中找到   流,Fabric会自动回答相应的   字典价值。

您应该能够让Fabric自动回答如下提示:

with settings(prompts={'Do you want to continue [Y/n]? ': 'Y'}):
    run('apt-get update')
    run('apt-get upgrade')

答案 1 :(得分:20)

我使用简单的回声管道来回答Fabric的提示。

run('echo "yes\n"| my_command')

答案 2 :(得分:12)

注意:这个答案已经有好几年了,而且平时织物有(有趣的是看起来很相似)的实现。请参阅下面的@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 adds answering to prompts to fabric with use of pexpect

答案 3 :(得分:4)

要在Timothée's excellent answer上展开一点,这是Fabric在检查prompts词典时使用的the code

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',请键入'yes',或者取消'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,
                  )
       )

答案 4 :(得分:2)

通过@BobNadler的评论

作为答案

运行("是| my_command");

答案 5 :(得分:1)

Fabric 2.1中,可以使用auto-respond example来完成此任务,该包可以通过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. 根据watcher docs结尾处讨论的注释:

    Responder的pattern参数被视为正则表达式,需要更多注意(请注意在上面的示例中我们必须如何逃避方括号),但也提供了更多功能。

    因此,请不要忘记在必要时转义(使用反斜杠)。