Ansible-navigator exec
Common Options and Explanations
<span>ansible-navigator exec</span> is equivalent to <span>podman run -it --rm <image> /bin/bash</span> (default is <span>/bin/bash</span>), <span>ansible-navigator exec</span> is commonly used to execute Ansible Ad-Hoc.
The available options are as follows:
| Parameter | Meaning | Example | Default Value |
<span>exec_command</span> |
Specifies the command to run in the execution environment (EE) | <span>ansible --version</span> |
<span>/bin/bash</span> |
<span>--exshell</span>, <span>--exec-shell</span> |
Whether to use shell to execute commands (e.g., via <span>/bin/sh -c</span>) to control whether to interpret redirection, variables, and other shell features |
<span>--exec-shell true</span> / <span>false</span> |
<span>true</span> |
Here, let’s explain <span>--exec-shell false</span>:
[root@ansible-controller ansible-navigator]# ansible-navigator exec --exec-shell false -- echo $HOSTNAME
ansible-controller
[root@ansible-controller ansible-navigator]# ansible-navigator exec --exec-shell false -- echo \$HOSTNAME
$HOSTNAME
[root@ansible-controller ansible-navigator]# ansible-navigator exec --exec-shell true -- echo \$HOSTNAME
159ceb83da82
[root@ansible-controller ansible-navigator]# ansible-navigator exec --exec-shell true -- echo $HOSTNAME
ansible-controller
[root@ansible-controller ansible-navigator]# ansible-navigator exec --exec-shell false -- sh -c 'echo $HOSTNAME'
0858792b5a5c
As we can see, when using <span>--exec-shell false</span>, the subsequent command is not parsed by Shell, and all commands are executed as is (similar to <span>ansible.builtin.command</span>), and the variable <span>HOSTNAME</span> cannot be printed correctly. Let’s look at the demonstration below:
[root@ansible-controller ansible-navigator]# ansible-navigator exec --exec-shell false -- echo qwez && echo qwer > /home/testfile
qwez
[root@ansible-controller ansible-navigator]# cat /home/testfile
qwer
[root@ansible-controller ansible-navigator]# ansible-navigator exec --exec-shell false -- echo qwez '&& echo qwer > /home/testfile'
qwez && echo qwer > /home/testfile
[root@ansible-controller ansible-navigator]# ansible-navigator exec --exec-shell false -- echo 'qwez && echo qwer > /home/testfile'
qwez && echo qwer > /home/testfile
[root@ansible-controller ansible-navigator]# ansible-navigator exec --exec-shell false -- 'echo qwez && echo qwer > /home/testfile'
[dumb-init] echo qwez && echo qwer > /home/testfile: No such file or directory
Here are two important points:
- 1. In the first two commands, we can see that
<span>&&</span>and<span>></span>seem to have executed, but this is not executed inside the container; only<span>echo qwez</span>is executed inside the container, and all commands after<span>&&</span>are executed on the host machine. This can be seen from<span>cat /home/testfile</span>, as the<span>/home/</span>directory is not mounted inside the container. If the command were executed inside the container, the host should not have the<span>testfile</span>file. - 2. The last command shows the effect of
<span>--exec-shell false</span>, as the last command passes<span>echo qwez && echo qwer > /home/testfile</span>as a whole to be executed in the container, which results in an error (similar to executing Shell with<span>ls -l</span>and<span>'ls -l'</span>in two different cases).
Finally, let’s demonstrate another example:
[root@ansible-controller ansible-navigator]# ansible-navigator \
--eei quay.io/ansible/awx-ee:24.6.1 exec --exec-shell false -- ansible all -m shell -i inventory -a "echo qwe"
worker1 | CHANGED | rc=0 >>
qwe
master1 | CHANGED | rc=0 >>
qwe
[root@ansible-controller ansible-navigator]# ansible-navigator \
--eei quay.io/ansible/awx-ee:24.6.1 exec --exec-shell true -- ansible all -m shell -i inventory -a "echo qwe"
master1 | CHANGED | rc=0 >>
qwe
worker1 | CHANGED | rc=0 >>
qwe
[root@ansible-controller ansible-navigator]# ansible-navigator \
--eei quay.io/ansible/awx-ee:24.6.1 exec --exec-shell true -- ansible all -m shell -i inventory -a '"echo qwe"'
worker1 | CHANGED | rc=0 >>
qwe
master1 | CHANGED | rc=0 >>
qwe
[root@ansible-controller ansible-navigator]# ansible-navigator \
--eei quay.io/ansible/awx-ee:24.6.1 exec --exec-shell true -- ansible all -m shell -i inventory -a '"echo qwe"'
master1 | CHANGED | rc=0 >>
qwe
worker1 | CHANGED | rc=0 >>
qwe
# This execution will report an error
[root@ansible-controller ansible-navigator]# ansible-navigator \
--eei quay.io/ansible/awx-ee:24.6.1 exec --exec-shell true -- ansible all -m shell -i inventory -a "echo qwe"
Here we can see the two results of <span>--exec-shell</span>:
- • When set to
<span>false</span>, the subsequent command is passed to the container for execution as is, and variables, pipes, or redirection are not parsed inside the container. - • When set to
<span>true</span>, the subsequent command will be parsed, and the first set of double quotes (or single quotes) will be expanded, so the quotes need to be escaped or wrapped in another layer. - • The last command that reports an error,
<span>ansible all -m shell -i inventory -a "echo qwe"</span>when passed to the container with<span>--exec-shell true</span>becomes<span>ansible all -m shell -i inventory -a echo qwe</span>.
<span>--exec-shell true</span>is somewhat similar to<span>bash -c</span>, where the command is first parsed by<span>bash -c</span>before execution.
[root@ansible-controller ansible-navigator]# bash -c ansible all -m shell -i inventory -a 'echo qwe'
[root@ansible-controller ansible-navigator]# ansible-navigator exec --exec-shell true -- bash -c 'echo $HOME'
[root@ansible-controller ansible-navigator]# bash -c 'echo $0 $1' dummy1 dummy2
dummy1 dummy2
Common Methods
One-time Ad-Hoc Execution
If you only need to execute a command once, you can use the following method, noting the use of <span>--exec-shell</span>.
[root@ansible-controller ansible-navigator]# ansible-navigator exec -- ansible all -m ping
master1 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/libexec/platform-python"
},
"changed": false,
"ping": "pong"
}
worker1 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/libexec/platform-python"
},
"changed": false,
"ping": "pong"
}
Executing Multiple Ad-Hoc Commands
If you want to execute multiple commands, you can first enter the container using the <span>bash</span> command, and then you can execute multiple commands without considering <span>--exec-shell</span>.
[root@ansible-controller ansible-navigator]# ansible-navigator --eei quay.io/ansible/awx-ee:24.6.1 exec -- bash
[root@630aacbc6226 ansible-navigator]# ansible all -m shell -a 'echo $HOSTNAME'
worker1 | CHANGED | rc=0 >>
worker1.example.com
master1 | CHANGED | rc=0 >>
master1.example.com
[root@630aacbc6226 ansible-navigator]# ansible all -m shell -a 'id'
worker1 | CHANGED | rc=0 >>
uid=10000(ansible) gid=10000(ansible) groups=10000(ansible),10(wheel) context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
master1 | CHANGED | rc=0 >>
uid=10000(ansible) gid=10000(ansible) groups=10000(ansible),10(wheel) context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
Verifying Several Options
Verifying <span>--penv</span> and <span>--senv</span>
[root@ansible-controller ansible-navigator]# export var1=redhat
[root@ansible-controller ansible-navigator]# export var2=fedora
[root@ansible-controller ansible-navigator]# ansible-navigator \
--eei quay.io/ansible/awx-ee:24.6.1 \
--penv=var1 --penv=var2 --senv=var3=debian --senv=var4=ubuntu exec -- bash
[root@7206dce5a2bb ansible-navigator]# env | grep var
var4=ubuntu
var1=redhat
var2=fedora
var3=debian
# Reopen a command line to check container properties
[root@ansible-controller ~]# podman inspect 7206dce5a2bb | jq .[0].HostConfig.Binds
[
"/root/ansible-navigator:/root/ansible-navigator/:rw,rprivate,rbind",
"/root/.ssh:/home/runner/.ssh/:rw,rprivate,rbind",
"/root/.ssh:/root/.ssh/:rw,rprivate,rbind",
"/tmp/ansible-navigator_loksnc9v/artifacts:/runner/artifacts/:rw,rprivate,rbind",
"/tmp/ansible-navigator_loksnc9v:/runner/:rw,rprivate,rbind",
"/mnt:/mnt:rw,rprivate,rbind"
]
Ansible-navigator run
<span>ansible-navigator run</span>is called through the<span>ansible-runner</span>interface, which is a standard set of interfaces. I am not familiar with it, so I won’t elaborate further.
Available Options
<span>ansible-navigator run</span> is used to execute Playbook scripts within a container, and the optional parameters are as follows:
| Parameter | Meaning | Example | Default Value |
<span>playbook</span> |
Specifies the name of the Playbook to run | <span>site.yml</span> |
Required, no default value |
<span>-i</span>, <span>--inventory</span> |
Specifies the inventory file path or a comma-separated list of hosts | <span>-i inventory.yml</span> / <span>-i host1,host2</span> |
<span>inventory</span> (current directory) |
<span>--ic</span>, <span>--inventory-column</span> |
Specifies the host property columns to display in the interactive inventory view | <span>--ic ansible_host</span> |
Empty (only host names displayed) |
<span>--ep</span>, <span>--enable-prompts</span> |
Enables password/interactive prompts (e.g., <span>--ask-vault-pass</span>, <span>pause</span>, <span>vars_prompt</span>, etc.), forces enabling <span>stdout</span> mode and disables artifact generation |
<span>--ep</span> |
Adding this option makes it <span>true</span>, not adding makes it <span>false</span> |
<span>--hp</span>, <span>--help-playbook</span> |
Displays the command line help for <span>ansible-playbook</span> |
<span>--hp</span> |
Adding this option makes it <span>true</span>, not adding makes it <span>false</span> |
<span>--pae</span>, <span>--playbook-artifact-enable</span> |
Whether to enable artifact generation after the Playbook execution; when enabled, <span>--ep</span> or interactive prompts are invalid (artifacts are not generated beforehand) |
<span>--pae false</span> |
<span>true</span> |
<span>--pas</span>, <span>--playbook-artifact-save-as</span> |
Custom artifact save path template; supports <span>{playbook_dir}</span>, <span>{playbook_name}</span>, <span>{time_stamp}</span>, <span>{playbook_status}</span> placeholders |
<span>--pas ./artifacts/{playbook_name}-{time_stamp}.json</span> |
<span>{playbook_dir}/{playbook_name}-artifact-{time_stamp}.json</span> |
<span>ansible-navigator run</span> also saves the records during Playbook execution, stored in two locations:
- • One location saves the running output, event logs, execution status, etc., set by
<span>--rad</span> - • The other location saves the execution results, which can be used to replay the process, set by
<span>--pas</span>
<span>ansible-navigator</span>can replay through the<span>replay</span>sub-option, which will be introduced later.
Also, it is worth mentioning that the
<span>--ep</span>option is used for executing Ansible Playbooks that require password input.
Executing a Playbook and Checking Related Logs
# The directory for the --rad option needs to be created in advance
[root@ansible-controller ansible-navigator]# mkdir ./runner-artifacts
# Execute the task
[root@ansible-controller ansible-navigator]# ansible-navigator \
--eei quay.io/ansible/awx-ee:24.6.1 \
--ll debug --la false --lf ./log/ansible-navigator.log \
-m stdout \
--rwje --rac 2 --rad ./runner-artifacts \
--penv=var1 --penv=var2 --senv=var3=debian --senv=var4=ubuntu \
--eev=/media:/media --eev=/mnt:/mnt:Z \
run test.yml \
--pas ./artifacts/{playbook_name}/{playbook_name}-{time_stamp}.json
# Check the generated files
[root@ansible-controller ansible-navigator]# tree log/
log/
└── ansible-navigator.log
0 directories, 1 file
[root@ansible-controller ansible-navigator]# tree artifacts/
artifacts/
└── test
└── test-2025-05-26T16:45:40.328121+00:00.json
1 directory, 1 file
[root@ansible-controller ansible-navigator]# tree runner-artifacts/
runner-artifacts/
├── artifacts
│ └── d1fd6023-1a25-4d93-b6c3-b911e91cd3ec
│ ├── callback
│ │ ├── awx_display.py
│ │ ├── __init__.py
│ │ └── __pycache__
│ │ ├── awx_display.cpython-312.pyc
│ │ ├── awx_display.cpython-39.pyc
│ │ └── __init__.cpython-312.pyc
│ ├── command
│ ├── env.list
│ ├── fact_cache
│ │ ├── master1
│ │ └── worker1
│ ├── job_events
│ │ ├── 1-030ab97d-65bf-4c7e-a5ff-5f04a59c039a.json
│ │ ├── 10-b2e3ded2-60d3-4c17-a572-618b562056d6.json
│ │ ├── 11-93351125-e519-4835-84d8-204838e69d55.json
│ │ ├── 12-96fc4af3-78e3-4f2d-9ee6-b8f55c3b657a.json
│ │ ├── 13-328b306a-e143-429a-9222-6e15651df522.json
│ │ ├── 2-367432dc-2a88-ca5d-1570-000000000003.json
│ │ ├── 3-367432dc-2a88-ca5d-1570-000000000009.json
│ │ ├── 4-3bc02273-8897-436d-818c-aaaf933b3c01.json
│ │ ├── 5-c3048ff9-fa85-4142-8178-b1c97f98570e.json
│ │ ├── 6-a14b6db9-2924-47ff-8f96-969eceb5696f.json
│ │ ├── 7-73a43174-74d3-4a00-b2b0-10fe3361c783.json
│ │ ├── 8-367432dc-2a88-ca5d-1570-000000000005.json
│ │ └── 9-c92f12ed-e5b7-44ca-bae6-101386c52297.json
│ ├── rc
│ ├── status
│ ├── stderr
│ └── stdout
└── project
7 directories, 26 files
ansible-navigator Log
By setting <span>--ll debug --la false --lf ./log/ansible-navigator.log</span>, the log level, log writing mode, and log file name are set, and the log file records what the <span>ansible-navigator</span> command did during execution:
[root@ansible-controller ansible-navigator]# head log/ansible-navigator.log
2025-05-26T16:45:37.880030+00:00 INFO 'ansible_navigator.setup_logger' New ansible-navigator instance, logging initialized
2025-05-26T16:45:37.880246+00:00 INFO 'ansible_navigator.setup_logger' New ansible-runner instance, logging initialized
2025-05-26T16:45:37.880288+00:00 DEBUG 'ansible_navigator.main' Jinja2==3.1.6
2025-05-26T16:45:37.880312+00:00 DEBUG 'ansible_navigator.main' MarkupSafe==3.0.2
2025-05-26T16:45:37.880332+00:00 DEBUG 'ansible_navigator.main' Parsley==1.3
2025-05-26T16:45:37.880349+00:00 DEBUG 'ansible_navigator.main' PyYAML==6.0.2
2025-05-26T16:45:37.880366+00:00 DEBUG 'ansible_navigator.main' ansible-builder==3.1.0
2025-05-26T16:45:37.880380+00:00 DEBUG 'ansible_navigator.main' ansible-compat==25.5.0
2025-05-26T16:45:37.880395+00:00 DEBUG 'ansible_navigator.main' ansible-core==2.18.6
2025-05-26T16:45:37.880409+00:00 DEBUG 'ansible_navigator.main' ansible-lint==25.4.0
[root@ansible-controller ansible-navigator]# tail log/ansible-navigator.log
2025-05-26T16:45:39.837575+00:00 DEBUG 'ansible_navigator.actions.run_playbook._dequeue' Drained 1 events
2025-05-26T16:45:39.839389+00:00 DEBUG 'ansible_navigator.runner.base._event_handler' ansible-runner event handle: {'uuid': '93351125-e519-4835-84d8-204838e69d55', 'counter': 11, 'stdout': '\x1b[0;32mok: [master1] => {\x1b[0m\r\n\x1b[0;32m "msg": "he"\x1b[0m\r\n\x1b[0;32m}\x1b[0m', 'start_line': 8, 'end_line': 11, 'runner_ident': 'd1fd6023-1a25-4d93-b6c3-b911e91cd3ec', 'event': 'runner_on_ok', 'pid': 15, 'created': '2025-05-26T16:45:39.838033+00:00', 'parent_uuid': '367432dc-2a88-ca5d-1570-000000000005', 'event_data': {'playbook': '/root/ansible-navigator/test.yml', 'playbook_uuid': '030ab97d-65bf-4c7e-a5ff-5f04a59c039a', 'play': 'qwe', 'play_uuid': '367432dc-2a88-ca5d-1570-000000000003', 'play_pattern': 'all', 'task': 'debug', 'task_uuid': '367432dc-2a88-ca5d-1570-000000000005', 'task_action': 'debug', 'resolved_action': 'ansible.builtin.debug', 'task_args': '', 'task_path': '/root/ansible-navigator/test.yml:6', 'host': 'master1', 'remote_addr': 'master1', 'res': {'msg': 'he', '_ansible_verbose_always': True, '_ansible_no_log': False, 'changed': False}, 'start': '2025-05-26T16:45:39.823525+00:00', 'end': '2025-05-26T16:45:39.837810+00:00', 'duration': 0.014285, 'event_loop': None, 'uuid': '93351125-e519-4835-84d8-204838e69d55'}}
2025-05-26T16:45:39.847728+00:00 DEBUG 'ansible_navigator.runner.base._event_handler' ansible-runner event handle: {'uuid': '96fc4af3-78e3-4f2d-9ee6-b8f55c3b657a', 'counter': 12, 'stdout': '\x1b[0;32mok: [worker1] => {\x1b[0m\r\n\x1b[0;32m "msg": "he"\x1b[0m\r\n\x1b[0;32m}\x1b[0m', 'start_line': 11, 'end_line': 14, 'runner_ident': 'd1fd6023-1a25-4d93-b6c3-b911e91cd3ec', 'event': 'runner_on_ok', 'pid': 15, 'created': '2025-05-26T16:45:39.847023+00:00', 'parent_uuid': '367432dc-2a88-ca5d-1570-000000000005', 'event_data': {'playbook': '/root/ansible-navigator/test.yml', 'playbook_uuid': '030ab97d-65bf-4c7e-a5ff-5f04a59c039a', 'play': 'qwe', 'play_uuid': '367432dc-2a88-ca5d-1570-000000000003', 'play_pattern': 'all', 'task': 'debug', 'task_uuid': '367432dc-2a88-ca5d-1570-000000000005', 'task_action': 'debug', 'resolved_action': 'ansible.builtin.debug', 'task_args': '', 'task_path': '/root/ansible-navigator/test.yml:6', 'host': 'worker1', 'remote_addr': 'worker1', 'res': {'msg': 'he', '_ansible_verbose_always': True, '_ansible_no_log': False, 'changed': False}, 'start': '2025-05-26T16:45:39.833500+00:00', 'end': '2025-05-26T16:45:39.846936+00:00', 'duration': 0.013436, 'event_loop': None, 'uuid': '96fc4af3-78e3-4f2d-9ee6-b8f55c3b657a'}}
2025-05-26T16:45:39.848193+00:00 DEBUG 'ansible_navigator.actions.run_playbook._dequeue' Drained 2 events
2025-05-26T16:45:40.328152+00:00 DEBUG 'ansible_navigator.actions.run_playbook.write_artifact' Formatted artifact file name set to ./artifacts/test/test-2025-05-26T16:45:40.328121+00:00.json
2025-05-26T16:45:40.328311+00:00 DEBUG 'ansible_navigator.actions.run_playbook.write_artifact' Resolved artifact file name set to /root/ansible-navigator/artifacts/test/test-2025-05-26T16:45:40.328121+00:00.json
2025-05-26T16:45:40.330785+00:00 INFO 'ansible_navigator.actions.run_playbook.write_artifact' Saved artifact as /root/ansible-navigator/artifacts/test/test-2025-05-26T16:45:40.328121+00:00.json
2025-05-26T16:45:40.330831+00:00 DEBUG 'ansible_navigator.actions.run_playbook.run_stdout' runner finished
ansible-navigator Execution Results
<span>--pas ./artifacts/{playbook_name}/{playbook_name}-{time_stamp}.json</span> sets the file for saving the results of Playbook execution, defaulting to <span>json</span> format:
[root@ansible-controller ansible-navigator]# head -n20 artifacts/test/test-2025-05-26T16:45:40.328121+00:00.json
{
"plays": [
{
"__play_name": "qwe",
"name": "qwe",
"pattern": "all",
"play": "qwe",
"play_pattern": "all",
"play_uuid": "367432dc-2a88-ca5d-1570-000000000003",
"playbook": "/root/ansible-navigator/test.yml",
"playbook_uuid": "030ab97d-65bf-4c7e-a5ff-5f04a59c039a",
"tasks": [
{
"__changed": false,
"__duration": "1s",
"__host": "master1",
"__number": 0,
"__result": "Ok",
"__task": "Gathering Facts",
"__task_action": "gather_facts",
[root@ansible-controller ansible-navigator]# tail artifacts/test/test-2025-05-26T16:45:40.328121+00:00.json
"\u001b[0;32mok: [worker1] => {\u001b[0m",
"\u001b[0;32m \"msg\": \"he\"\u001b[0m",
"\u001b[0;32m}\u001b[0m",
"",
"PLAY RECAP *********************************************************************",
"\u001b[0;32mmaster1\u001b[0m : \u001b[0;32mok=2 \u001b[0m changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 ",
"\u001b[0;32mworker1\u001b[0m : \u001b[0;32mok=2 \u001b[0m changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 "
],
"version": "2.0.0"
}
This file can be used for replaying, which will be introduced later.
ansible-navigator Event Records and Task Status During Execution
<span>--rwje --rac 2 --rad ./runner-artifacts</span> sets where the events and task statuses are recorded, and how many to keep at most:
# A task's event directory
[root@ansible-controller ansible-navigator]# ll runner-artifacts/artifacts/
total 0
drwx------. 5 root root 141 May 27 00:45 d1fd6023-1a25-4d93-b6c3-b911e91cd3ec
# All task event-related files
[root@ansible-controller ansible-navigator]# ls runner-artifacts/artifacts/d1fd6023-1a25-4d93-b6c3-b911e91cd3ec/
callback command env.list fact_cache job_events rc status stderr stdout
# Check if the task execution was successful
[root@ansible-controller ansible-navigator]# cat runner-artifacts/artifacts/d1fd6023-1a25-4d93-b6c3-b911e91cd3ec/rc && echo
0
[root@ansible-controller ansible-navigator]# cat runner-artifacts/artifacts/d1fd6023-1a25-4d93-b6c3-b911e91cd3ec/status && echo
successful
# List the fact variable cache files
[root@ansible-controller ansible-navigator]# ls runner-artifacts/artifacts/d1fd6023-1a25-4d93-b6c3-b911e91cd3ec/fact_cache/
master1 worker1
# All event records are stored in separate files
[root@ansible-controller ansible-navigator]# ls runner-artifacts/artifacts/d1fd6023-1a25-4d93-b6c3-b911e91cd3ec/job_events/
1-030ab97d-65bf-4c7e-a5ff-5f04a59c039a.json 13-328b306a-e143-429a-9222-6e15651df522.json 5-c3048ff9-fa85-4142-8178-b1c97f98570e.json 9-c92f12ed-e5b7-44ca-bae6-101386c52297.json
10-b2e3ded2-60d3-4c17-a572-618b562056d6.json 2-367432dc-2a88-ca5d-1570-000000000003.json 6-a14b6db9-2924-47ff-8f96-969eceb5696f.json
11-93351125-e519-4835-84d8-204838e69d55.json 3-367432dc-2a88-ca5d-1570-000000000009.json 7-73a43174-74d3-4a00-b2b0-10fe3361c783.json
12-96fc4af3-78e3-4f2d-9ee6-b8f55c3b657a.json 4-3bc02273-8897-436d-818c-aaaf933b3c01.json 8-367432dc-2a88-ca5d-1570-000000000005.json
# Each file records an event
[root@ansible-controller ansible-navigator]# cat runner-artifacts/artifacts/d1fd6023-1a25-4d93-b6c3-b911e91cd3ec/job_events/8-367432dc-2a88-ca5d-1570-000000000005.json | jq
{
"uuid": "367432dc-2a88-ca5d-1570-000000000005",
"counter": 8,
"stdout": "\r\nTASK [debug] *******************************************************************",
"start_line": 6,
"end_line": 8,
"runner_ident": "d1fd6023-1a25-4d93-b6c3-b911e91cd3ec",
"event": "playbook_on_task_start",
"pid": 15,
"created": "2025-05-26T16:45:39.822701+00:00",
"parent_uuid": "367432dc-2a88-ca5d-1570-000000000003",
"event_data": {
"playbook": "/root/ansible-navigator/test.yml",
"playbook_uuid": "030ab97d-65bf-4c7e-a5ff-5f04a59c039a",
"play": "qwe",
"play_uuid": "367432dc-2a88-ca5d-1570-000000000003",
"play_pattern": "all",
"task": "debug",
"task_uuid": "367432dc-2a88-ca5d-1570-000000000005",
"task_action": "debug",
"resolved_action": "ansible.builtin.debug",
"task_args": "",
"task_path": "/root/ansible-navigator/test.yml:6",
"name": "debug",
"is_conditional": false,
"uuid": "367432dc-2a88-ca5d-1570-000000000005"
}
}
# Variable records
[root@ansible-controller ansible-navigator]# cat runner-artifacts/artifacts/d1fd6023-1a25-4d93-b6c3-b911e91cd3ec/env.list && echo
ANSIBLE_UNSAFE_WRITES=1
AWX_ISOLATED_DATA_DIR=/runner/artifacts/d1fd6023-1a25-4d93-b6c3-b911e91cd3ec
ANSIBLE_CACHE_PLUGIN_CONNECTION=/runner/artifacts/d1fd6023-1a25-4d93-b6c3-b911e91cd3ec/fact_cache
var3=debian
var4=ubuntu
var1=redhat
var2=fedora
ANSIBLE_CALLBACK_PLUGINS=/runner/artifacts/d1fd6023-1a25-4d93-b6c3-b911e91cd3ec/callback
ANSIBLE_STDOUT_CALLBACK=awx_display
ANSIBLE_RETRY_FILES_ENABLED=False
ANSIBLE_HOST_KEY_CHECKING=False
ANSIBLE_CACHE_PLUGIN=jsonfile
# Command executed in the container
[root@ansible-controller ansible-navigator]# cat runner-artifacts/artifacts/d1fd6023-1a25-4d93-b6c3-b911e91cd3ec/command | jq
{
"command": [
"podman",
"run",
"--rm",
"--tty",
"--interactive",
"-v",
"/root/ansible-navigator/:/root/ansible-navigator/",
"--workdir",
"/root/ansible-navigator",
"-v",
"/root/.ssh/:/home/runner/.ssh/",
"-v",
"/root/.ssh/:/root/.ssh/",
"--group-add=root",
"--ipc=host",
"-v",
"/root/ansible-navigator/runner-artifacts/artifacts/:/runner/artifacts/:Z",
"-v",
"/root/ansible-navigator/runner-artifacts/:/runner/:Z",
"-v",
"/media:/media",
"-v",
"/mnt:/mnt:Z",
"--env-file",
"/root/ansible-navigator/runner-artifacts/artifacts/d1fd6023-1a25-4d93-b6c3-b911e91cd3ec/env.list",
"--quiet",
"--name",
"ansible_runner_d1fd6023-1a25-4d93-b6c3-b911e91cd3ec",
"--user=root",
"quay.io/ansible/awx-ee:24.6.1",
"ansible-playbook",
"/root/ansible-navigator/test.yml",
"-i",
"/root/ansible-navigator/inventory"
],
"cwd": "/root/ansible-navigator",
"env": {
"ANSIBLE_UNSAFE_WRITES": "1",
"AWX_ISOLATED_DATA_DIR": "/runner/artifacts/d1fd6023-1a25-4d93-b6c3-b911e91cd3ec",
"ANSIBLE_CACHE_PLUGIN_CONNECTION": "/runner/artifacts/d1fd6023-1a25-4d93-b6c3-b911e91cd3ec/fact_cache",
"var3": "debian",
"var4": "ubuntu",
"var1": "redhat",
"var2": "fedora",
"ANSIBLE_CALLBACK_PLUGINS": "/runner/artifacts/d1fd6023-1a25-4d93-b6c3-b911e91cd3ec/callback",
"ANSIBLE_STDOUT_CALLBACK": "awx_display",
"ANSIBLE_RETRY_FILES_ENABLED": "False",
"ANSIBLE_HOST_KEY_CHECKING": "False",
"ANSIBLE_CACHE_PLUGIN": "jsonfile"
}
}
<span>job_events</span>files are only generated when the<span>--rwje</span>option is set.
<span>fact_cache</span>requires setting<span>fact_caching=jsonfile</span>and also setting the directory for<span>fact_caching_connection=</span>, for example,<span>fact_caching_connection=./cache</span>to cache fact variables to files.
<span>stdout</span>and<span>stderr</span>files are not demonstrated, but their names suggest that the former is used to record standard output, while the latter is used to record error output.The content of the
<span>command</span>file shows how<span>ansible-navigator</span>starts the container, and also verifies some previous container-related options, such as<span>--eev</span>,<span>--penv</span>, and<span>--senv</span>.
The above <span>d1fd6023-1a25-4d93-b6c3-b911e91cd3ec</span> is the event record of a task, and executing the task again will create a new directory to record events:
[root@ansible-controller ansible-navigator]# ls runner-artifacts/artifacts/
d1fd6023-1a25-4d93-b6c3-b911e91cd3ec be5683e0-908c-4d66-a149-4ea835921b70
Since the <span>--rac 2</span> option is set, a maximum of 2 event records will be kept, so there will be at most two directories under <span>runner-artifacts/artifacts/</span>. Checking this directory after executing the task again will find that <span>d1fd6023-1a25-4d93-b6c3-b911e91cd3ec</span> has been deleted:
[root@ansible-controller ansible-navigator]# ls runner-artifacts/artifacts/
0ba4a2ed-ad87-46cc-ab37-b44fa0162058 be5683e0-908c-4d66-a149-4ea835921b70
Finally, it is worth mentioning that when executing a Playbook, if you want to cache fact variables, it only supports
<span>jsonfile</span>mode.
Manually Inputting Information During Playbook Execution
If you need to manually input information during Playbook execution, you need to add the <span>--ep</span> option:
[root@ansible-controller ansible-navigator]# ansible-navigator \
--eei quay.io/ansible/awx-ee:24.6.1 \
--ll debug --la false --lf ./log/ansible-navigator.log \
-m stdout \
--rwje --rac 2 --rad ./runner-artifacts \
--penv=var1 --penv=var2 --senv=var3=debian --senv=var4=ubuntu \
--eev=/media:/media --eev=/mnt:/mnt:Z \
run test.yml \
--pas ./artifacts/{playbook_name}/{playbook_name}-{time_stamp}.json \
--ep -- --become --ask-become-pass
BECOME password:
PLAY [qwe] ************************
TASK [Gathering Facts] ************
ok: [worker1]
ok: [master1]
...output omitted...
Here are two important points:
- • After
<span>--ep</span>, the replayable log file ending with<span>.json</span>will not be generated - • At the end, we can see
<span>-- --become --ask-become-pass</span>, where the<span>--</span>serves to pass the following<span>--become --ask-become-pass</span>parameters to the<span>ansible</span>inside the container rather than being parsed by the<span>ansible-navigator</span>command.