In previous Ansible tutorials we saw how easy it is to understand the basic concepts of this fantastic automation tool, how to write our first playbooks, how to organize tasks into roles, and how to use Ansible Vault to protect sensitive data. This time, we focus on an interactive tool which let us execute tasks on the fly, targeting single hosts or host groups: the Ansible console.
In this tutorial you will learn:
- How to install the Ansible console on the most used Linux distributions
- How to use the Ansible console

Category | Requirements, Conventions or Software Version Used |
---|---|
System | Distribution agnostic |
Software | ansible |
Other | Privileged access to your Linux system as root or via the sudo command in order to perform system-wide installation of required packages |
Conventions | # – requires given linux-commands to be executed with root privileges either directly as a root user or by use of sudo command$ – requires given linux-commands to be executed as a regular non-privileged user |
Introduction and installation
Ansible console is a Read Eval Print Loop (REPL) environment from which we can execute tasks on the fly and immediately visualize their results. The ansible-console utility is part of the ansible-core
package, which on Fedora and Fedora-based distributions we can install with the following command:
$ sudo dnf install ansible-core
To perform the installation on Debian and on Debian-base distributions, instead, we can run:
$ sudo apt install ansible-core
Using Archlinux? The ansible-core package is available in the “Extra” repository, so it can be easily installed with pacman
:
$ sudo pacman -S ansible-core
It is also possible to install the package in a distribution-agnostic way, using pip:
$ pip install --user ansible-core
Invoking the ansible-console
We use ansible-console practically in the same manner we use ansible-playbook, since the two utilities share the vast majority of options. The most basic possible way to invoke the console is by running:
$ ansible-console
Our shell prompt will change to confirm the Ansible REPL environment is accepting commands:
[WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all' Welcome to the ansible console. Type help or ? to list commands. doc@all (0)[f:5]$
The warning message you see above is due to the fact that we didn’t specify any inventory file. In such cases Ansible generates an implicit localhost for us when we use “localhost” as a target. You can see this is reflected in the console prompt, where “doc” is the Ansible “remote user” and “all” is the host group we are targeting.
doc@all (0)[f:5]$
By default, the user we invoke the ansible-console as, is also used for remote connections; another one, however, can be specified as argument to the --user
option when we invoke the console, or, from the console itself, by executing the remote_user
command:
doc@all (0)[f:5]$ remote_user username
Since, as stated in the warning, the “all” group doesn’t match the implicit localhost, we can see a 0
between parenthesis in the prompt, which is the number of matched hosts. After this, between square brackets, we can see the number of available forks: 5, (the default). Forks are the simultaneous connections Ansible can use on a task. The number of available forks can be specified when invoking the console, as argument to the -f
option:
$ ansible-console -f 7
Alternatively, it can be changed from the console itself, with the fork
command:
doc@all (0)[f:5]$ forks 7
Since our current configuration matches no hosts, the tasks we will run will have no effect. Since at the moment we can only target the implicit localhost, to do something effective, we should “switch” to it, let’s see how to do it.
Targeting specific hosts or groups
How can we target a specific host (or host group) from the Ansible console? We can do it by using the cd
command, as if we were changing working directory. To target the implicit localhost, for example, we would run:
doc@all (0)[f:5]$ cd localhost
The prompt will immediately reflect the change of target:
doc@localhost (1)[f:5]$
Notice how, as expected, the number of matched host has become
1
. The cd
command can be also used to target specific hosts or groups explicitly defined into an inventory file. Let’s see an example. Suppose we have the following, very basic, ansible inventory, saved into a file named inventory.ini:
[workstations] localhost ansible_connection=local [servers] feanor ansible_host=192.168.0.39
In the inventory we explicitly defined a “localhost”, and two groups : “workstations” (which includes localhost), and “servers”, which contains only one host (feanor). To point the ansible-console to this inventory file, we pass it as argument to the -i
option:
$ ansible-console -i inventory.ini
The console prompt reports the number of matched hosts:
doc@all (2)[f:5]$
To get a list the available hosts, we can use the list
command:
doc@all (2)[f:5]$ list localhost feanor
To list the available groups, instead, we use list groups
:
doc@all (2)[f:5]$ list groups all servers ungrouped workstations
Above we can see the groups we explicitly defined in the inventory file appearing in the output of the command, together with other two groups automatically created by Ansible: “all” and “ungrouped”. The former is the group which encompasses all available hosts, the latter represents a way to reference all the hosts which are not part of any group.
In order to switch to a specific group, we can use cd
, exactly as we did in the previous examples:
doc@all (2)[f:5]$ cd workstations
Getting a list of the available modules
As we already know, Ansible functionalities are organized in modules. To list all available modules from the Ansible console, we can use the help
command:
doc@all (2)[f:5]$ help
The list will be printed on screen (output truncated):
Documented commands (type help <topic>): ======================================== EOF amazon.aws.autoscaling_group amazon.aws.autoscaling_group_info amazon.aws.aws_az_info amazon.aws.aws_caller_info amazon.aws.cloudformation amazon.aws.cloudformation_info amazon.aws.cloudtrail amazon.aws.cloudtrail_info amazon.aws.cloudwatch_metric_alarm amazon.aws.cloudwatch_metric_alarm_info amazon.aws.cloudwatchevent_rule amazon.aws.cloudwatchlogs_log_group amazon.aws.cloudwatchlogs_log_group_info amazon.aws.cloudwatchlogs_log_group_metric_filter [...]
To obtain help about a specific module, we can, again, use the “help” command, this time, passing the name of the module as argument. For instance, to read the documentation of the
ansible.builtin.file
module, we would run:
doc@all (2)[f:5]$ help ansible.builtin.file
Here is the result of invoking the command above:
Manage files and file properties Parameters: path Path to the file being managed. state If C(absent), directories will be recursively deleted, and files or symlinks will be unlinked. In the case of a directory, if C(diff) is declared, you will see the files and folders deleted listed under C(path_contents). Note that C(absent) will not cause C(file) to fail if the C(path) does not exist as the state did not change. src Path of the file to link to. recurse Recursively set the specified file attributes on directory contents. force Force the creation of the symlinks in two cases: the source file does not exist (but will appear later); the destination exists and is a file (so, we need to unlink the C(path) file and create symlink to the C(src) file in place of it). follow This flag indicates that filesystem links, if they exist, should be followed. modification_time This parameter indicates the time the file's modification time should be set to. modification_time_format When used with C(modification_time), indicates the time format that must be used. access_time This parameter indicates the time the file's access time should be set to. access_time_format When used with C(access_time), indicates the time format that must be used. mode The permissions the resulting filesystem object should have. owner Name of the user that should own the filesystem object, as would be fed to I(chown). group Name of the group that should own the filesystem object, as would be fed to I(chown). seuser The user part of the SELinux filesystem object context. serole The role part of the SELinux filesystem object context. setype The type part of the SELinux filesystem object context. selevel The level part of the SELinux filesystem object context. unsafe_writes Influence when to use atomic operation to prevent data corruption or inconsistent reads from the target filesystem object. attributes The attributes the resulting filesystem object should have.
Running a task
Running a tasks from the Ansible console is pretty easy. All we have to do is to invoke the module we want to use and provide required parameters. Let’s suppose we want to install a Python package with pip using the ansible.builtin.pip
module, targeting only “localhost”. Here is what we would do. First we would switch to “localhost” with the cd
command:
doc@all (2)[f:5]$ cd localhost
Than, we would invoke the module and pass the name of the package we want to install as argument to the “name” parameter. In the example below we install youtube-dl, an utility we can use to download videos from Youtube and from many other platforms:
doc@localhost (1)[f:5]$ ansible.builtin.pip name=youtube-dl
We can immediately visualize the output of the task:
localhost | CHANGED => { "ansible_facts": { "discovered_interpreter_python": "/usr/bin/python3" }, "changed": true, "cmd": [ "/usr/bin/python3", "-m", "pip.__main__", "install", "youtube-dl" ], "name": [ "youtube-dl" ], "requirements": null, "state": "present", "stderr": "", "stderr_lines": [], "stdout": "Defaulting to user installation because normal site-packages is not writeable\nCollecting youtube-dl\n Downloading youtube_dl-2021.12.17-py2.py3-none-any.whl (1.9 MB)\n ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 1.9/1.9 MB 4.1 MB/s eta 0:00:00\nInstalling collected packages: youtube-dl\nSuccessfully installed youtube-dl-2021.12.17\n", "stdout_lines": [ "Defaulting to user installation because normal site-packages is not writeable", "Collecting youtube-dl", " Downloading youtube_dl-2021.12.17-py2.py3-none-any.whl (1.9 MB)", " ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 1.9/1.9 MB 4.1 MB/s eta 0:00:00", "Installing collected packages: youtube-dl", "Successfully installed youtube-dl-2021.12.17" ], "version": null, "virtualenv": null }
In the example above, we installed a single package, therefore we provided a string as value of the “name” parameter. It is also possible to pass multiple elements, so to install multiple packages. In a playbook we would use a list, in the Ansible console, instead, we separate items with a comma:
doc@localhost (1)[f:5]$ ansible.builtin.pip name=youtube-dl,bs4
Becoming another user
Certain tasks modifies the global state of the system, therefore we must invoke them with elevated privileges. Just as we would do when using the ansible-playbook utility, we invoke ansible-shell with the -K
option (short for --ask-become-pass
); we will be prompted to provide our password, since the default method of becoming another user is “sudo”:
$ ansible-console -i inventory.ini --ask-become-pass BECOME password:
Once we provide the password, we can become root by toggling the “become” flag:
doc@all (1)[f:5]$ become true
The prompt will reflect the change: the text color will become red, and $
will change to #
:
doc@all (1)[f:5]#
Now we can invoke the task requiring administrative privileges. We can, for example, use the ansible.builtin.package
module to install a package system-wide:
ansible.builtin.package name=git
To switch back to an unprivileged user we can simply use:
doc@all (1)[f:5]# become false
Running a shell command
Sometimes, we may want to run a standard shell command without leaving the Ansible console environment. This can be done by prefixing the command we want to run with a !
(this may remind you of something if you are a Vim user). Just as an example, suppose we want to print the name of the current working directory with pwd
. We would run:
doc@all (1)[f:5]$ !pwd
Parameter expansions and command substitution also work with this technique:
doc@all (1)[f:5]$ !echo ${HOSTNAME} localhost | CHANGED | rc=0 >> fingolfin doc@all (1)[f:5]$ !echo "today is $(date)" localhost | CHANGED | rc=0 >> today is Thu Jul 20 04:16:03 PM CEST 2023
Exiting the Ansible console
Once we are done working in the Ansible console, to return to the system shell, all we have to do is to use the exit
command:
doc@all (1)[f:5]$ exit Ansible-console was exited.
Conclusions
This tutorial is just the last one in our series about Ansible. Here we saw how to invoke the Ansible console and how to read its prompt, how to get information about available modules, how to execute a task, and how to navigate through hosts and groups. We also sow how to run tasks with elevated privileges, and, finally how to exit the console.