通过 Ansible-navigator 执行 Ad-Hoc 和 Playbook

Ansible-navigator exec

常用选项和解释

ansible-navigator exec 相当于 podman run -it --rm <image> /bin/bash(默认为 /bin/bash),ansible-navigator exec 常用于执行 Ansible Ad-Hoc

可用选项如下:

参数 含义 示例 默认值
exec_command 指定在执行环境(EE)中运行的命令 ansible --version /bin/bash
--exshell, --exec-shell 是否使用 shell 来执行命令(如通过 /bin/sh -c)用于控制是否解释重定向、变量等 shell 特性 --exec-shell true / false true

这里单独解释一下 --exec-shell false

[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

可以看到 --exec-shell false 时,后边接的命令不会被 Shell 做解析,所有的命令都会原封不动的执行(类似 ansible.builtin.command),变量 HOSTNAME 无法正常打印,再看下边的演示:

[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

这里强调两个东西:

  1. 在前两个命令中可以看到 &&> 好像执行了,但是这个并不是在容器内执行的,在容器内执行的只有 echo qwez&& 之后的命令全部是在宿主机执行的。通过 cat /home/testfile 可以看出来,/home/ 目录并没有挂载到容器内,如果命令是在容器内执行的,宿主机应该没有 testfile 文件。

  2. 最后一个命令可以看到 --exec-shell false 的效果,最后一个命令将 echo qwez && echo qwer > /home/testfile 放在一个单引号里了,因为 --exec-shell false,所以 echo qwez && echo qwer > /home/testfile 作为整体传递给容器执行,所以会有报错(类似在 Shell 中分别执行 ls -l'ls -l' 的两种情况)。

    [root@ansible-controller ansible-navigator]# 'ls -l'
    -bash: ls -l: command not found
    [root@ansible-controller ansible-navigator]# ls -l
    total 196
    -rw-r--r--. 1 root root     57 May 25 22:18 ansible.cfg
    -rw-r--r--. 1 root root 174193 May 25 23:23 ansible-navigator.log
    -rw-r--r--. 1 root root   6462 May 25 22:57 ansible-navigator.yaml
    drwxr-xr-x. 3 root root     47 May 26 00:05 artifacts
    -rw-r--r--. 1 root root    205 May 25 22:18 inventory
    drwxr-xr-x. 2 root root      6 May 25 22:24 runner-artifacts
    -rw-r--r--. 1 root root      5 May 25 23:26 testfile
    -rw-r--r--. 1 root root    105 May 25 22:23 test.yml

最后再演示一个:

[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

# 这个执行会报错
[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"

这里可以看到 --exec-shell 的两种结果:

  • false 时,后边命令就会原封不动的传递给容器去执行,且在容器内不会解析变量、管道符或重定向等 Shell 特性
  • true 时,后边的命令会做解析,第一组双引号(或单引号)会被展开,所以引号需要做转义或者多套一层
  • 最下边那个报错的命令,ansible all -m shell -i inventory -a "echo qwe"--exec-shell true 时传递给容器的命令是 ansible all -m shell -i inventory -a echo qwe

--exec-shell true 有点类似 bash -c,命令传递给容器后先被 bash -c 解析,然后再执行。

[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

常用方式

一次性执行 Ad-Hoc

如果只执行一次命令,那可以用下边这个方式执行,注意 --exec-shell 的使用。

[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"
}

执行多个 Ad-Hoc

如果要执行多条命令,那么可以先用 bash 命令进入到容器,然后就可以执行多条命令了,这个就不需要考虑 --exec-shell 了。

[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

验证几个选项

验证 --penv--senv

[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

# 重新开一个命令行来查看容器属性
[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

ansible-navigator run 是通过 ansible-runner 接口来调用容器的,ansible-runner 是一套标准的接口,现在不熟,不做过多介绍。

可用选项

ansible-navigator run 用于在容器内执行 Playbook 剧本,可选参数如下:

参数 含义 示例 默认值
playbook 指定要运行的 Playbook 名称 site.yml 必填,无默认值
-i, --inventory 指定 inventory 文件路径或以逗号分隔的主机列表 -i inventory.yml / -i host1,host2 inventory(当前目录)
--ic, --inventory-column 指定在交互式 inventory 视图中显示的主机属性列 --ic ansible_host 空(仅显示主机名)
--ep, --enable-prompts 启用密码/交互提示(如 --ask-vault-passpausevars_prompt 等),会强制启用 stdout 模式并禁用 artifact 生成 --ep 添加选项为 true,不加为 false
--hp, --help-playbook 显示 ansible-playbook 的命令行帮助 --hp 添加选项为 true,不加为 false
--pae, --playbook-artifact-enable 是否启用 playbook 执行完成后的 artifact 生成;当启用 --ep 或交互提示时,这个选线无效(前置不生成 artifact --pae false true
--pas, --playbook-artifact-save-as 自定义 artifact 保存路径模板;支持 playbook_dirplaybook_nametime_stampplaybook_status 这些占位符 --pas ./artifacts/{playbook_name}-{time_stamp}.json {playbook_dir}/{playbook_name}-artifact-{time_stamp}.json

ansible-navigator run 在执行 Playbook 的时候还会将记录保存下来,总共保存在两个位置:

  • 一个位置保存 Playbook 执行过程中的运行输出、事件日志、执行状态等,通过 --rad 设置
  • 另一个位置保存执行结果,可以用来回放过程,通过 --pas 设置

ansible-navigator 通过 replay 子选项进行回放,后边介绍。

还要提一下 --ep 选项,这个用于执行 Ansible Playbook 输入密码的情况。

执行一个 Playbook 并检查相关日志

# 需要提前创建 --rad 选项的目录
[root@ansible-controller ansible-navigator]# mkdir ./runner-artifacts

# 执行任务
[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

# 检查生成的文件
[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 日志

通过 --ll debug --la false --lf ./log/ansible-navigator.log 设置了日志等级,日志写入模式和日志文件名,日志文件里记录了执行过程中 ansible-navigator 命令做了什么:

[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:39.880018+00:00 DEBUG 'ansible_navigator.runner.base._event_handler' ansible-runner event handle: {'uuid': '328b306a-e143-429a-9222-6e15651df522', 'counter': 13, 'stdout': '\r\nPLAY RECAP *********************************************************************\r\n\x1b[0;32mmaster1\x1b[0m                    : \x1b[0;32mok=2   \x1b[0m changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   \r\n\x1b[0;32mworker1\x1b[0m                    : \x1b[0;32mok=2   \x1b[0m changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   ', 'start_line': 14, 'end_line': 19, 'runner_ident': 'd1fd6023-1a25-4d93-b6c3-b911e91cd3ec', 'event': 'playbook_on_stats', 'pid': 15, 'created': '2025-05-26T16:45:39.879084+00:00', 'parent_uuid': '030ab97d-65bf-4c7e-a5ff-5f04a59c039a', 'event_data': {'playbook': '/root/ansible-navigator/test.yml', 'playbook_uuid': '030ab97d-65bf-4c7e-a5ff-5f04a59c039a', 'changed': {}, 'dark': {}, 'failures': {}, 'ignored': {}, 'ok': {'master1': 2, 'worker1': 2}, 'processed': {'master1': 1, 'worker1': 1}, 'rescued': {}, 'skipped': {}, 'artifact_data': {}, 'uuid': '328b306a-e143-429a-9222-6e15651df522'}}
2025-05-26T16:45:39.889901+00:00 DEBUG 'ansible_navigator.actions.run_playbook._dequeue' Drained 1 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 执行的结果

--pas ./artifacts/{playbook_name}/{playbook_name}-{time_stamp}.json 设置 Playbook 执行的结果保存的文件,默认 json 格式:

[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"
}

这个文件可以用于回放,后边介绍。

ansible-navigator 执行过程中事件的记录和任务状态

--rwje --rac 2 --rad ./runner-artifacts 设置了事件和任务状态记录在哪,并且最多保留几个:

# 一个任务的事件目录
[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

# 所有任务事件相关文件
[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

# 查看任务执行是否成功
[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

# 列出事实变量缓存文件
[root@ansible-controller ansible-navigator]# ls runner-artifacts/artifacts/d1fd6023-1a25-4d93-b6c3-b911e91cd3ec/fact_cache/
master1  worker1

# 所有事件分文件记录
[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

# 每一个文件记录一个事件
[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"
  }
}

# 变量记录
[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

# 执行容器的命令
[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"
  }
}

job_events 目录下的文件只有设置 --rwje 后才会生成。

fact_cache 需要设置 fact_caching=jsonfile,并且 fact_caching_connection= 有设置目录,比方说 fact_caching_connection=./cache 才会将事实变量缓存到文件中。

stdout 文件和 stderr 文件没有演示,但是看名字也能猜出来了,前者是用来记录标准输出,后者是用来记录错误输出的。

可以通过 command 文件的内容可以看到 ansible-navigator 是如何启动容器的,同时也可以验证之前的一些容器相关选项,比方说 --eev--penv--senv

上边的 d1fd6023-1a25-4d93-b6c3-b911e91cd3ec 是一次任务的事件记录,再次执行任务会出现新的目录记录事件:

[root@ansible-controller ansible-navigator]# ls runner-artifacts/artifacts/
be5683e0-908c-4d66-a149-4ea835921b70  d1fd6023-1a25-4d93-b6c3-b911e91cd3ec

因为设置了 --rac 2,所以最多保存 2 个事件记录,所以 runner-artifacts/artifacts/ 下最多有两个目录,再次执行任务检查这个目录会发现 d1fd6023-1a25-4d93-b6c3-b911e91cd3ec 被删除了:

[root@ansible-controller ansible-navigator]# ls runner-artifacts/artifacts/
0ba4a2ed-ad87-46cc-ab37-b44fa0162058  be5683e0-908c-4d66-a149-4ea835921b70

最后提一个,ansible-navigator run 执行 Playbook 时,如果想要缓存事实变量的话只支持 jsonfile 模式。

在执行 Playbook 时手动输入信息

如果在执行 Playbook 时需要手动输入信息,需要添加 --ep 选项:

[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...

这里强调两点:

  • --ep 后,就不会生成 .json 结尾的那个可回放的日志文件
  • 最后边可以看到 -- --become --ask-become-pass,这里的 -- 作用是将后边的 --become --ask-become-pass 参数传递给容器内的 ansible 而不是被 ansible-navigator 命令解析
通过 Ansible-navigator 执行 Ad-Hoc 和 Playbook
https://www.linuxstudynotes.com/2025/05/30/ansible/%e9%80%9a%e8%bf%87-ansible-navigator-%e6%89%a7%e8%a1%8c-ad-hoc-%e5%92%8c-playbook/
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇