Ansible expect Module: Handle Interactive Prompts & Input (Guide)
By Luca Berton · Published 2024-01-01 · Category: installation
How to handle interactive command prompts with Ansible expect module (ansible.builtin.expect). Automate password prompts, respond to questions.
The ansible.builtin.expect module runs commands that require interactive input — responding to password prompts, confirmations, license agreements, and multi-step installers. It uses Python's pexpect library to match prompts and send responses.
Prerequisites
The pexpect library must be installed on the remote host:
- name: Install pexpect
ansible.builtin.pip:
name: pexpect
state: present
become: true
Or via system packages:
- name: Install pexpect (Debian/Ubuntu)
ansible.builtin.apt:
name: python3-pexpect
state: present
become: true
- name: Install pexpect (RHEL/CentOS)
ansible.builtin.dnf:
name: python3-pexpect
state: present
become: true
See also: Ansible expect Module: Automate Interactive Commands (Examples)
Basic Usage
- name: Change user password
ansible.builtin.expect:
command: passwd johndoe
responses:
"New password:": "SecureP@ss123"
"Retype new password:": "SecureP@ss123"
become: true
no_log: true
Key Parameters
| Parameter | Description | Default |
|-----------|-------------|---------|
| command | Command to run | (required) |
| responses | Dict of prompt→response pairs | (required) |
| timeout | Seconds to wait for each prompt | 30 |
| echo | Show command output | false |
| chdir | Working directory | — |
| creates | Skip if file exists | — |
| removes | Skip if file doesn't exist | — |
See also: Ansible Set File Permissions 755: chmod with file Module Guide
Pattern Matching with Regex
The responses keys are Python regular expressions:
- name: Accept license agreement
ansible.builtin.expect:
command: /opt/installer/setup.sh
responses:
# Regex patterns for flexible matching
"(?i)do you accept.*license": "yes"
"(?i)enter.*installation.*directory": "/opt/myapp"
"(?i)continue.*\\?": "y"
"(?i)password": "{{ vault_app_password }}"
timeout: 120
no_log: true
Real-World Examples
MySQL Secure Installation
- name: Secure MySQL installation
ansible.builtin.expect:
command: mysql_secure_installation
responses:
"Enter password for user root:": "{{ mysql_root_pass }}"
"VALIDATE PASSWORD": "y"
"Please enter.*strength.*password": "2"
"Change the password for root": "n"
"Remove anonymous users": "y"
"Disallow root login remotely": "y"
"Remove test database": "y"
"Reload privilege tables now": "y"
timeout: 30
become: true
no_log: true
SSH Key Generation
- name: Generate SSH key non-interactively
ansible.builtin.expect:
command: ssh-keygen -t ed25519 -C "deploy@example.com"
responses:
"Enter file in which to save": "/home/deploy/.ssh/id_ed25519"
"Enter passphrase": ""
"Enter same passphrase": ""
creates: /home/deploy/.ssh/id_ed25519
become: true
become_user: deploy
Software Installation
- name: Install application interactively
ansible.builtin.expect:
command: /tmp/installer.bin
responses:
"Press ENTER to continue": ""
"(?i)accept.*license.*\\(yes/no\\)": "yes"
"Installation directory": "/opt/app"
"(?i)create.*directory": "y"
"Admin username": "admin"
"Admin password": "{{ vault_admin_pass }}"
"Confirm password": "{{ vault_admin_pass }}"
"Start service now": "yes"
timeout: 300
creates: /opt/app/bin/server
become: true
no_log: true
Handling Repeated Prompts
When a prompt appears multiple times, provide a list of responses:
- name: Interactive setup with repeated prompts
ansible.builtin.expect:
command: /opt/app/setup.sh
responses:
"Enter value:":
- "first_value"
- "second_value"
- "third_value"
"Confirm.*\\?": "yes"
timeout: 60
See also: Add Windows Registry on Windows-like systems - Ansible module win_regedit
Timeout Handling
- name: Long-running interactive command
ansible.builtin.expect:
command: /opt/backup/full-backup.sh
responses:
"(?i)password": "{{ vault_backup_pass }}"
"(?i)continue": "yes"
timeout: 3600 # 1 hour
async: 7200 # Ansible-level timeout: 2 hours
poll: 30
Idempotent expect
- name: Initialize database (only if not done)
ansible.builtin.expect:
command: /opt/app/bin/init-db
responses:
"Admin email:": "admin@example.com"
"Admin password:": "{{ vault_db_admin_pass }}"
creates: /opt/app/data/.initialized
no_log: true
Security: Always Use no_log
⚠️ Always set no_log: true when responses contain passwords or secrets:
# BAD — passwords appear in Ansible output and logs
- ansible.builtin.expect:
command: passwd user1
responses:
"New password:": "secret123"
# GOOD — output is suppressed
- ansible.builtin.expect:
command: passwd user1
responses:
"New password:": "{{ vault_user_password }}"
no_log: true
When NOT to Use expect
Many interactive commands have non-interactive alternatives:
| Interactive Command | Non-Interactive Alternative |
|---|---|
| passwd | ansible.builtin.user module with password |
| mysql_secure_installation | Direct SQL commands |
| ssh-keygen (with passphrase) | community.crypto.openssh_keypair |
| apt install (prompts) | ansible.builtin.apt (handles it) |
| fdisk | community.general.parted |
Use expect as a last resort — native modules are more reliable and idempotent.
FAQ
Why do I get "No module named 'pexpect'"?
Install pexpect on the remote host (not the control node). Use pip install pexpect or install the system package python3-pexpect.
How do I handle a prompt that appears multiple times?
Use a list of responses instead of a single string. Ansible sends each response in order for successive matches of the same prompt pattern.
Why doesn't my pattern match?
Response keys are Python regex patterns. Special characters (?, (, ), [, ]) need escaping with \\. Use (?i) for case-insensitive matching. Test patterns with python3 -c "import re; print(re.search(r'your_pattern', 'test_string'))".
Conclusion
Use ansible.builtin.expect for interactive commands that have no non-interactive alternative. Always use no_log: true for security, regex patterns for flexible matching, and creates/removes for idempotency. Prefer native Ansible modules when available.
Related Articles
• Ansible command Module • Ansible shell vs command • Ansible Vault Deep DiveCategory: installation