I want to run a command which prompts me to enter yes/no or y/n or whatever. If I just run the command local("my_command") then it stops and asks me for input. When I type what is needed, script continues to work. How can I automatically respond to the prompt?
 
    
    - 3,702
- 6
- 34
- 49
- 
                    possible duplicate of [How to get Fabric to automatically (instead of user-interactively) interact with shell commands? Combine with pexpect?](http://stackoverflow.com/questions/8291380/how-to-get-fabric-to-automatically-instead-of-user-interactively-interact-with) – Steffen Opel May 07 '12 at 16:28
- 
                    1@aemdy could you please change the answer to be the one suggested by Timothée Jeannin. I have seen several other questions like this, and the currently selected answer is outdated. It would make it much easier for folks to get the right answer :). – Breedly Feb 05 '17 at 15:08
6 Answers
Starting from version 1.9, Fabric includes a way of managing this properly. 
The section about Prompts in the Fabric documentation says:
The prompts dictionary allows users to control interactive prompts. If a key in the dictionary is found in a command’s standard output stream, Fabric will automatically answer with the corresponding dictionary value.
You should be able to make Fabric automatically answer prompts like this:
with settings(prompts={'Do you want to continue [Y/n]? ': 'Y'}):
    run('apt-get update')
    run('apt-get upgrade')
 
    
    - 9,652
- 2
- 56
- 65
- 
                    3
- 
                    3@aemdy This should really be the accepted answer at this point, works out of the box with no issues. – Nathan Cox Dec 14 '15 at 19:09
- 
                    1Tip: Your prompts dictionary keys are matched using a built-in Fabric function io._endswith. If you can't figure out why your patterns aren't matching, it might be because you forgot to include a space at the end. For example "UNIX password: " or "New password: " or "Retype new password: " – scottwed Jun 07 '16 at 18:47
- 
                    
- 
                    I'm struggling to figure out how I could use this to, first, trigger a sequence of actions, and only *then* reply to the prompt. Is there any way? – Shon Aug 18 '16 at 00:59
- 
                    1Fabric uses `.endswith` for its check, so make sure you include trailing spaces in the string you use as a key in the `prompts` dictionary. – Christian Long Nov 21 '16 at 16:22
- 
                    I find that there is a white space after '[Y/n]? ', is it necessary or not? – Kingname Dec 12 '16 at 07:31
- 
                    1Does this work with `local()` function? I tried something simple, like `with settings(prompts={'Continue? ': 'Y'}): local('read -p "Continue? " var', capture=True)` and it was blocked on the prompt. Update: It looks like input was still connected to console :( – haridsv May 17 '17 at 11:46
- 
                    1To answer my own question from above, it looks like prompts are handled in ssh io while `local` is just a simple wrapper on top of `Popen` so this won't work. I guess we need to use `pexpect`. – haridsv May 17 '17 at 11:55
I have used simple echo pipes to answer prompts with Fabric.
run('echo "yes\n"| my_command')
 
    
    - 441
- 2
- 3
Note: this answer is several years old, and in the mean time fabric has (interestingly similar looking) implementation of this. See the answer by @timothée-jeannin below.
See 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
 
    
    - 1
- 1
 
    
    - 3,169
- 4
- 32
- 55
- 
                    Cool project, but it'd be better if it could not have to rely on putting a python file on the server. Need to check this out more and see if I can assist. – Morgan May 08 '12 at 02:34
- 
                    1Thanks Morgan, I agree. I have suggested something on the fabric list, but got no response so far, and ended up writing fexpect which cost me less time than getting into the internals of Fabric. – Jasper van den Bosch May 08 '12 at 10:38
- 
                    Right, I think I saw that, but didn't perhaps grok the intent. I'm pretty interested in pushing this further, and have had some experience in Fabric internals, and before I found Fabric, pxssh/pexpect. – Morgan May 08 '12 at 21:37
- 
                    
- 
                    it doesnt work for me: http://pastebin.com/vAPwVxaR code: http://pastebin.com/HFUJkb6J – Nov 24 '13 at 16:27
- 
                    Please post this as a new question and send it to me. Also include your python code if possible – Jasper van den Bosch Nov 25 '13 at 17:59
- 
                    1The blog post link currently unavailable, "ilogue.com is for sale"... Here's the archived page: http://web.archive.org/web/20140624141333/http://ilogue.com/jasper/blog/fexpect--dealing-with-prompts-in-fabric-with-pexpect/ – FooF Dec 01 '15 at 05:50
- 
                    
- 
                    Fabric has awesome built in support for this now. Check a few comments down for the 31 point answer. – Breedly Feb 05 '17 at 15:06
- 
                    1@Breedly I have added a note to this answer as a heads up for visitors – Jasper van den Bosch Feb 05 '17 at 19:08
In Fabric 2.1, this can be accomplished using the auto-respond example that is available through the invoke package (a dependency of 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>
Note that this is not limited to sudo passwords and can be used anywhere where you have a pattern to match for and a canned response (that may not be a password).
There are a couple of tips:
- pty=Trueis NOT necessary but could be important because it makes the flow seem more realistic. e.g. if you had a prompt expecting a yes/no answer to proceed, without it(- pty=True) your command would still run; except, your choice/input(specified by- response) won't be shown as typed as the answer as one might expect
- The patternspecified within theRespondercan often include spaces at the end of the line so try adding spaces when thewatcherdoesn't seem to match.
- According to the note discussed at the end of the watcher docs: - The pattern argument to Responder is treated as a regular expression, requiring more care (note how we had to escape our square-brackets in the above example) but providing more power as well. - So, don't forget to escape (using backslashes) where necessary. 
To expand a bit on Timothée's excellent answer, here's the code that Fabric uses when checking the prompts dictionary.
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 uses .endswith for its check, so make sure you include trailing spaces in the string you use as a key in the prompts dictionary.
For example - let's say you are trying to automate the Django test database prompt
Type 'yes' if you would like to try deleting the test database 'test_my_app', or 'no' to cancel:
All we need is enough of the end of the prompt so that it is unique. Include trailing spaces.
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,
                  )
       )
 
    
    - 1
- 1
 
    
    - 10,385
- 6
- 60
- 58
Putting this as an answer though its a comment from @BobNadler
run("yes | my_command");
 
    
    - 593
- 2
- 10
- 22
 
    