32

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

4

6 回答 6

49

从 version 开始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')
于 2014-08-19T07:39:55.263 回答
23

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

run('echo "yes\n"| my_command')
于 2012-05-07T13:57:58.927 回答
13

注意:这个答案已经有几年的历史了,与此同时,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 添加对提示的回答

于 2012-05-07T13:38:08.937 回答
4

为了扩展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”,请输入“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,
                  )
       )
于 2016-11-21T16:38:09.897 回答
4

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. can中pattern指定的Responder通常在行尾包含空格,因此当watcher似乎不匹配时尝试添加空格。
  3. 根据观察者文档末尾讨论的注释:

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

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

于 2018-06-29T08:45:51.160 回答
2

尽管这是@BobNadler 的评论,但将其作为答案

运行(“是|我的命令”);

于 2015-05-29T00:14:19.350 回答