变量

在实际应用场景中,我们希望一些任务、配置根据设备性能的不同而产生差异,比如使用本机 CPU 核数动态配置 Nginx 的 worker_processes 参数,可能有一组主机的应用配置文件几乎相同,但略有不同的配置项可以引用变量。在 Ansible 中使用变量的目的是方便处理系统之间的差异。变量名的命名规则由字母、数字和下划线组合而成,变量必须以字母开头,如 “foo_port” 是一个合法的变量,“foo5” 也是可以的,“foo-port”、“foo port”、“foo.port” 和 “12” 都是非法的变量命名。在 Inventory 中定义变量见 9.3.2 节和 9.3.3 节,在 playbook 定义变量见 9.6 节,建议回顾一下,加深记忆。

Jinja2过滤器

Jinja2 是 Python 下一个广泛应用的模板引擎,它的设计思想类似于 Django 的模板引擎,并扩展了其语法和一系列强大的功能,官网地址: http://jinja.pocoo.org/ 。下面介绍一下 Ansible 使用 Jinja2 强大的过滤器(Filters)功能。

使用格式:{{ 变量名 | 过滤方法 }}

下面是实现获取一个文件路径变量过滤出文件名的一个示例:

{{ path | basename }}

获取文件所处的目录名:

{{ path | dirname }}

下面为一个完整的示例,实现从 “/etc/profile” 中过滤出文件名 “profile”,并输出重定向到 /tmp/testshell 文件中。

---
- hosts: 192.168.1.21
      vars:
        filename: /etc/profile
      tasks:
        - name: "shell1"
      shell: echo {{ filename | basename }} >> /tmp/testshell

本地Facts

我们可以通过 Facts 来获取目标主机的系统信息,当这些信息还不能满足我们的功能需求时,可以通过编写自定义的 Facts 模块来实现。当然,还有一个更简单的实现方法,就是通过本地 Facts 来实现。只需在目标设备 /etc/ansible/facts.d 目录定义 JSON、INI 或可执行文件的 JSON 输出,文件扩展名要求使用 “.fact”,这些文件都可以作为 Ansible 的本地 Facts,例如,在目标设备 192.168.1.21 定义三个变量,供以后 playbook 进行引用。

ansible/facts.d/preferences.fact
[general]
max_memory_size=32
max_user_processes=3730
open_files=65535

在主控端运行 ansible 192.168.1.21-m setup -a "filter=ansible_local" 可看到定义的结果,返回结果如下:

192.168.1.21 | success >> {
    "ansible_facts": {
        "ansible_local": {
            "preferences": {
                "general": {
                    "max_memory_size": "32",
                    "max_user_processes": "3730",
                    "open_files": "65535"
                }
            }
        }
    },
    "changed": false
}

注意返回 JSON 的层次结构,preferences(facts 文件名前缀)→general(INI 的节名)→key:value(INI 的键与值),最后就可以在我们的模板或 playbook 中通过以下方式进行调用:

{{ ansible_local.preferences.general. open_files }}

注册变量

变量的另一个用途是将一条命令的运行结果保存到变量中,供后面的 playbook 使用。下面是一个简单的示例:

- hosts: web_servers
  tasks:
    - shell: /usr/bin/foo
      register: foo_result
      ignore_errors: True
    - shell: /usr/bin/bar
      when: foo_result.rc == 5

上述示例注册了一个 foo_result 变量,变量值为 shell:/usr/bin/foo 的运行结果,ignore_errors: True 为忽略错误。变量注册完成后,就可以在后面 playbook 中使用了,当条件语句 when: foo_result.rc == 5 成立时,shell: /usr/bin/bar 命令才会运行,其中 foo_result.rc 为返回 /usr/bin/foo 的 resultcode(返回码)。图9-8返回 “rc=0” 的返回码。

image 2023 12 08 21 32 23 317
Figure 1. 图9-8 命令执行结果