playbook中的变量使用

本章主要介绍playbook中的变量

  • 自定义变量
  • 使用变量文件
  • 字典变量
  • 列表变量
  • 注册变量
  • facts变量
  • 内置变量
  • 变量的过滤器

为了能够写出更实用的playbook,需要在playbook中使用变量。下面来讲解playbook 中常见的变量。本章实验都在demo2文件夹下操作,先把 demo2目录创建出来并 把ansible.cfg和 hosts拷贝进去

[blab@aaa1 ~]$ mkdir demo2
[blab@aaa1 ~]$ cp ansible.cfg hosts demo2/
[blab@aaa1 ~]$ ls 
ansible.cfg  demo1  demo2  hosts
[blab@aaa1 ~]$ cd demo2/
[blab@aaa1 demo2]$ ls
ansible.cfg  hosts
[blab@aaa1 demo2]$ 

1.1 手动定义变量

通过vars来定义变量,vars和 tasks对齐。定义变量的格式如下

1 vars:
2  变量1: 值1
3  变量2: 值2

定义变量时,不可有重复的变量,否则后面定义的变量的值会覆盖前面定义的变量的值

1 vars:
2  aa: value1
3  bb: value2
4  aa: value3

引用变量时用 {{变量名}} ,大括号内侧两边是否有空格是无所谓的

1 {{变量名}}
2 {{ 变量名 }}
3 {{ 变量名 }}
4 {{ 变量名 }}

练习:写一个名称为1.yml的playbook,里面定义以下3个变量

myname1=tom

myname2=tom2

myname3=tom3

然后打印mynamel的值

​
[blab@aaa1 demo2]$ vim 1.yml
[blab@aaa1 demo2]$ cat 1.yml 
---
- hosts: aaa3
  vars: 
    myname1: tom1
    myname2: tom2
    myname3: tom3
  tasks:
  - name: 打印变量
    debug: msg="变量myname的值是{{myname1}}"
[blab@aaa1 demo2]$ 

​

运行此playbook

[blab@aaa1 demo2]$ ansible-playbook 1.yml 

PLAY [aaa3] *************************************************************************

TASK [Gathering Facts] **************************************************************
ok: [aaa3]

TASK [打印变量] *************************************************************************
ok: [aaa3] => {
    "msg": "变量myname的值是tom1"
}

PLAY RECAP **************************************************************************
aaa3                       : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

[blab@aaa1 demo2]$ 

可以看到,打印了myname1的值为 tom1

定义变量时,同一个变量定义多次,后面定义的生效,修改1.yml的内容如下

[blab@aaa1 demo2]$ cat 1.yml
---
- hosts: aaa3 
  vars: 
    myname1: tom1
    myname2: tom2
    myname3: tom3
    myname1: tom2
  tasks:
  - name: 打印变量
    debug: msg="变量myname的值是{{myname1}}"
[blab@aaa1 demo2]$ 

这里定义了两次 mynamel 这个变量,第一次定义的值为toml,第二次定义的值为 tom2。下面运行此playbook查看结果

[blab@aaa1 demo2]$ ansible-playbook 1.yml
[WARNING]: While constructing a mapping from /home/blab/demo2/1.yml, line 4, column
5, found a duplicate dict key (myname1). Using last defined value only.

PLAY [aaa3] *************************************************************************

TASK [Gathering Facts] **************************************************************
ok: [aaa3]

TASK [打印变量] *************************************************************************
ok: [aaa3] => {
    "msg": "变量myname的值是tom2"
}

PLAY RECAP **************************************************************************
aaa3                       : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

因为mynamel重复定义了两次,所以运行此playbook时会有提示,意思是变量重复定义 了,且后面定义的myname1生效,打印的结果为 tom2

1.2 变量文件

如果定义的变量太多,可以把变量拿出来单独放在一个文件中,然后在playbook中通过 vars_files引用此变量文件,那么就可以直接使用此变量文件中的变量了,就像变量文件中的 变量直接在YAML文件中定义似的,这样更方便管理。

例如,创建文件vars.yml

[blab@aaa1 demo2]$ cat vars.yml
myv1: aaa
myv2: bbb
myv2: ccc
[blab@aaa1 demo2]$ 

修改1.yml 的内容如下

[blab@aaa1 demo2]$ cat 1.yml
---
- hosts: aaa3 
  vars_files:
  - vars.yml
  vars: 
    myname1: tom1
    myname2: tom2
    myname3: tom3
    myname1: tom2
  tasks:
  - name: 打印变量
    debug: msg="变量myname的值是{{myname1}}"
  - name: 打印变量myv1的值
    debug: msg='变量myv1的值是{{myv1}}'
[blab@aaa1 demo2]$ 

这里通过vars_files来引用变量文件 vars.yml,然后打印变量myvl的值

[blab@aaa1 demo2]$ ansible-playbook 1.yml
[WARNING]: While constructing a mapping from /home/blab/demo2/1.yml, line 6, column
5, found a duplicate dict key (myname1). Using last defined value only.
[WARNING]: While constructing a mapping from /home/blab/demo2/vars.yml, line 1,
column 1, found a duplicate dict key (myv2). Using last defined value only.

PLAY [aaa3] *************************************************************************

TASK [Gathering Facts] **************************************************************
ok: [aaa3]

TASK [打印变量] *************************************************************************
ok: [aaa3] => {
    "msg": "变量myname的值是tom2"
}

TASK [打印变量myv1的值] *******************************************************************
ok: [aaa3] => {
    "msg": "变量myv1的值是aaa"
}

PLAY RECAP **************************************************************************
aaa3                       : ok=3    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

1.3 字典变量

所谓字典(dictionaries简写为dict),就是存储多个变量的容器,可以把字典理解为一个木桶,里面存放了很多个变量。如图所示,两个木桶xx和yy,里面分别存储了3个变量: aa=1,bb=2, cc=3

playbook中的变量使用_第1张图片

同一个字典中定义的多个变量不可有重复值,否则后面定义的变 量会覆盖前面定义的变量。 要是引用木桶中的变量,必须指定是哪个木桶中的变量。例如,要引用木桶xx中的变量 aa,则使用xx.aa。 字典是在vars下定义的,语法如下。

1 字典名:
2 var1: value2
3 var2: value2
4 ...

注意:在字典中定义这一个个变量时,变量前面是不加“-”的,且定义变量没有先后顺序

通过“字典名.变量名”这种格式来引用变量,看下面的例子

[blab@aaa1 demo2]$ cat 2.yml
---
- hosts: aaa3
  vars:
   dict1:
    myv1: aaa
    myv2: bbb
    myv3: ccc
   dict2:
    myv1: 111
    myv2: 222
    myv3: 333
  tasks:
  - name: 打印第一个变量
    debug: msg="{{dict1.myv1}}"
[blab@aaa1 demo2]$ 

这里定义了两个字典dict1和 dict2,里面分别有3个变量,最后通过dict1.myvl引用了字典dick1中的变量myvl。通过ansible-playbook 2.yml运行的结果应该为aaa

[blab@aaa1 demo2]$ ansible-playbook 2.yml 

PLAY [aaa3] *************************************************************************

TASK [Gathering Facts] **************************************************************
ok: [aaa3]

TASK [打印第一个变量] **********************************************************************
ok: [aaa3] => {
    "msg": "aaa"
}

PLAY RECAP **************************************************************************
aaa3                       : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

[blab@aaa1 demo2]$ 

如果在同一个字典中出现了相同的变量名,则后面定义的变量的值会覆盖前面定义的变量的值

1.4 列表变量

列表变量和字典变量比较容易弄混。下面来看一个例子,定义一个员工表,里面有3个员工,每个员工通过以下3个属性记录

  (1)uname:记录用户名

(2)age:记录年龄

(3)sex:记录性别

这个员工表的内容如下

1 employee:
2 uname: zhangsan
3 age: 22
4 sex: man
5
6 uname: lisi
7 age: 24
8 sex: man
9
10 uname: xiaohong
11 age: 21
12 sex: wuman

为了看得清楚,这里把每个用户用空白行隔开了。每个用户都是由3个变量组成的一个整体,这个整体是员工表employee的一个元素。所以,这个员工表有3个元素,即3个人

每个元素都有uname,所以列表employee共有3个uname,但是这3个uname不应该是冲突的,因为它们分别属于不同的人

但是为了防止误会,每个元素的第一个变量前都加上一个“-”,表示它是这个元素的第 一个变量。所以,员工表改成如下内容
 

1 employee:
2 - uname: zhangsan
3 age: 22
4 sex: man
5
6 - uname: lisi
7 age: 24
8 sex: man
9
10 - uname: xiaohong
11 age: 21
12 sex: wuman

这样看起来就清晰了很多,这里employee就是一个列表

那如果想获取某个元素(某个员工)的信息该怎么办呢?可以通过employee[n]来获取, 这里的n叫作下标,下标从0开始

例如,要获取第一个用户的信息,则使用employee[0]即可,employee[0]得到的值如下

1 uname: zhangsan
2 age: 22
3 sex: man

可以看到,这是由3个变量组成的,这3个变量组成了一个字典,即employee[0]就是一个字典。如果想获取第一个用户的用户名,则可以通过employee[0].uname来获取

所以,员工表employee是由3个字典组成的;employee[0]、employee[1]、employee[2]

列表和字典的不同如下

(1)列表的每个元素的第一个变量都是以“-”开头

(2)字典的每个变量前面都不带“-”

练习1:写一个名称为3-list.yml 的playbook,定义一个用户列表,里面包含3个用户,每个用户由uname、sex、age组成

[blab@aaa1 demo2]$ cat 3.yml 
---
- hosts: aaa3
  vars:
   users:
   - uname: tom
     sex: man
     age: 19
   - uname: bob
     sex: man
     age: 20
   - uname: mary
     sex: woman
     age: 21
  tasks:
  - name: 打印第一个变量
    debug: msg={{users[2]}}
[blab@aaa1 demo2]$ 

这里列表users定义了3个元素,现在要获取第3个元素用users[2]来表示,运行结果如下

[blab@aaa1 demo2]$ ansible-playbook 3.yml 

PLAY [aaa3] *************************************************************************

TASK [Gathering Facts] **************************************************************
ok: [aaa3]

TASK [打印第一个变量] **********************************************************************
ok: [aaa3] => {
    "msg": {
        "age": 21,
        "sex": "woman",
        "uname": "mary"
    }
}

PLAY RECAP **************************************************************************
aaa3                       : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

[blab@aaa1 demo2]$ 

如果要获取第3个用户的用户名,修改3-list.yml的内容如下

[blab@aaa1 demo2]$ cat 3.yml
---
- hosts: aaa3
  vars:
   users:
   - uname: tom
     sex: man
     age: 19
   - uname: bob
     sex: man
     age: 20
   - uname: mary
     sex: woman
     age: 21
  tasks:
  - name: 打印第三个变量
    debug: msg={{users[2].uname}}
[blab@aaa1 demo2]$ 

运行后的结果

[blab@aaa1 demo2]$ ansible-playbook 3.yml 

PLAY [aaa3] *************************************************************************

TASK [Gathering Facts] **************************************************************
ok: [aaa3]

TASK [打印第三个变量] **********************************************************************
ok: [aaa3] => {
    "msg": "mary"    ///第三个变量
}

PLAY RECAP **************************************************************************
aaa3                       : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

定义列表时,也可以直接写值不写变量,通过如下方式来定义


1 listname:
2 ‐ var1
3 ‐ var2
4 ‐ var3

这种定义变量的方式可以换成如下内容

1.5 数字变量的运算

在YAML 文件中定义的变量,其值如果是数字,则可以进行数学运算。常见的数学运算符包括+(加)、-(减)、*(乘)、/(除)、**(次方)

练习:写一个名称为4-vars.yml 的 playbook,定义了变量aa,值为3,然后求aa*2和aa的3次方

[blab@aaa1 demo2]$ cat 4.yml
---
- hosts: aaa3
  vars:
    aa: 3
  tasks:
  - name: 3乘2的值
    debug: msg={{aa*2}}
  - name: 3的3次方
    debug: msg="{{3**3}}"   
[blab@aaa1 demo2]$ 

运行此playbook

[blab@aaa1 demo2]$ ansible-playbook 4.yml 

PLAY [aaa3] *************************************************************************

TASK [Gathering Facts] **************************************************************
ok: [aaa3]

TASK [3乘2的值] ************************************************************************
ok: [aaa3] => {
    "msg": "6"
}

TASK [3的3次方] ************************************************************************
ok: [aaa3] => {
    "msg": "27"
}

PLAY RECAP **************************************************************************
aaa3                       : ok=3    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

[blab@aaa1 demo2]$ 

1.6 注册变量

在playbook中用shell模块执行某个系统命令后,在结果中是不会显示这个命令结果的,这个和在命令行中用ansible命令调用shell模块不一样

练习:写一个 playbook,在里面执行系统命令hostname

[blab@aaa1 demo2]$ cat 5.yml
---
- hosts: aaa3
  tasks:
  - name: 执行第一个操作命令
    shell: 'hostname'
[blab@aaa1 demo2]$ 

运行此playbook

[blab@aaa1 demo2]$ ansible-playbook 5.yml 

PLAY [aaa3] *************************************************************************

TASK [Gathering Facts] **************************************************************
ok: [aaa3]

TASK [执行第一个操作命令] ********************************************************************
changed: [aaa3]

PLAY RECAP **************************************************************************
aaa3                       : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

可以看到,没有任何输出。如果想查看这个shell命令的结果,可以把shell 命令的结果保存在一个变量中,这个变量就是注册变量,然后打印这个变量的值即可。修改5.yml的内容如下

[blab@aaa1 demo2]$ cat 5.yml 
---
- hosts: aaa3
  tasks:
  - name: 执行第一个操作命令
    shell: 'hostname'
    register: aa
  - name: 打印注册变量的值
    debug: msg={{aa}}

[blab@aaa1 demo2]$ 

运行此playbook

[blab@aaa1 demo2]$ ansible-playbook 5.yml

PLAY [aaa3] *************************************************************************

TASK [Gathering Facts] **************************************************************
ok: [aaa3]

TASK [执行第一个操作命令] ********************************************************************
changed: [aaa3]

TASK [打印注册变量的值] *********************************************************************
ok: [aaa3] => {
    "msg": {
        "changed": true,
        "cmd": "hostname",
        "delta": "0:00:00.002859",
        "end": "2023-12-22 11:55:08.700649",
        "failed": false,
        "rc": 0,
        "start": "2023-12-22 11:55:08.697790",
        "stderr": "",
        "stderr_lines": [],
        "stdout": "aaa2",
        "stdout_lines": [
            "aaa2"
        ]
    }
}

PLAY RECAP **************************************************************************
aaa3                       : ok=3    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

结果中msg后面的内容就是aa的值,可以看到aa就是一个字典。其中cmd是执行的系统命令,rc是此命令的返回值,stdout表示此命令的结果

所以,如果只获取这个命令的结果,只要打印字典aa中的 stdout 变量即可。修改5-regl.ym1的内容如下

[blab@aaa1 demo2]$ cat 5.yml 
---
- hosts: aaa3
  tasks:
  - name: 执行第一个操作命令
    shell: 'hostname'
    register: aa
  - name: 打印注册变量的值
    debug: msg={{aa.stdout}}

[blab@aaa1 demo2]$ 

运行此playbook

[blab@aaa1 demo2]$ ansible-playbook 5.yml

PLAY [aaa3] *************************************************************************

TASK [Gathering Facts] **************************************************************
ok: [aaa3]

TASK [执行第一个操作命令] ********************************************************************
changed: [aaa3]

TASK [打印注册变量的值] *********************************************************************
ok: [aaa3] => {
    "msg": "aaa3"
}

PLAY RECAP **************************************************************************
aaa3                       : ok=3    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

[blab@aaa1 demo2]$ 

这里正确的显示hostname的值为aaa3

1.7 facts变量
ansible通过setup模块是可以获取到被管理主机的所有信息的,这些信息都是以变量的方式存在,这些变量称为facts,前面在setup模块中已经介绍过了。现在写一个名称为6-fact.yml的playbook,用于打印rhel802的IP和主机名,命令如下

[blab@aaa1 demo2]$ cat 6.yml
---
- hosts: aaa3
  vars:
    list1: ['aaa: ']
  tasks:
  - name: 打印IP
    debug: msg={{ansible_default_ipv4.address}}
  - name: 打印主机名
    debug: msg={{ansible_fqdn}}
[blab@aaa1 demo2]$ 

这里打印 IP 用到的fact变量是 ansible default ipv4.address,打印主机名用到的fact变量是 ansible_fqdn,运行结果如下

[blab@aaa1 demo2]$ ansible-playbook 6.yml

PLAY [aaa3] *************************************************************************

TASK [Gathering Facts] **************************************************************
ok: [aaa3]

TASK [打印IP] *************************************************************************
ok: [aaa3] => {
    "msg": "192.168.56.217"
}

TASK [打印主机名] ************************************************************************
ok: [aaa3] => {
    "msg": "aaa3"
}

PLAY RECAP **************************************************************************
aaa3                       : ok=3    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

[blab@aaa1 demo2]$ 

这里显示aaa3的IP是192.168.56.217,主机名是aaa3

1.8 内置变量groups

在 ansible 中,除用户手动去定义一些变量外,还有一些内置的变量,这些变量不需要用户定义就可以直接使用

groups用于列出清单文件中所有定义的主机组及里面的主机,看下面的例子

[blab@aaa1 demo2]$ cat 7.yml
---
- hosts: aaa3
  tasks: 
  - name: xxx
    debug: msg={{groups}}
[blab@aaa1 demo2]$ 

运行此playbook

[blab@aaa1 demo2]$ ansible-playbook 7.yml

PLAY [aaa3] *************************************************************************

TASK [Gathering Facts] **************************************************************
ok: [aaa3]

TASK [xxx] **************************************************************************
ok: [aaa3] => {
    "msg": {
        "all": [
            "aaa2",
            "aaa3"
        ],
        "ungrouped": [
            "aaa2",
            "aaa3"
        ]
    }
}

PLAY RECAP **************************************************************************
aaa3                       : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

这里显示了清单文件中所有的主机组及里面的主机信息

如果只想列出某个主机组,可以通过“groups['主机组名]”或“groups.主机组名”来表示。修改7.yml的内容如下

[blab@aaa1 demo2]$ cat 7.yml
---
- hosts: aaa3
  tasks: 
  - name: xxx
    debug: msg={{groups['all']}}

[blab@aaa1 demo2]$ 

这里只显示主机组all中的主机,运行结果如下

[blab@aaa1 demo2]$ ansible-playbook 7.yml

PLAY [aaa3] *************************************************************************

TASK [Gathering Facts] **************************************************************
ok: [aaa3]

TASK [xxx] **************************************************************************
ok: [aaa3] => {
    "msg": [
        "aaa2",
        "aaa3"
    ]
}

PLAY RECAP **************************************************************************
aaa3                       : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

可以看到,这里只显示了all主机组中的主机

groups['all']可以改写成 groups.all

​
[blab@aaa1 demo2]$ cat 7.yml
---
- hosts: aaa3
  tasks: 
  - name: xxx
    debug: msg={{groups.all}}

[blab@aaa1 demo2]$ 

​

1.9 内置变量hostvars

hostvars用来显示指定主机的 fact变量,用法如下

 hostvars[' 主机名 '].键值

此变量一般用于,当某个play的 hosts 中只写了A主机组,但是同时想在此play中显示B主机组中的信息,这时可以选择此变量

练习:写一个playbook,里面包含一个play,里面的hosts指定为aaa2,但是要显示 aaa3的IP地址

内容如下

[blab@aaa1 demo2]$ cat 8.yml
---
- hosts: aaa3
   
- hosts: aaa2
  tasks:
  - name: 打印aaa3的IP地址
    debug: msg={{hostvar.aaa3.ansible_default_ipv4_address}}
[blab@aaa1 demo2]$ 

运行后的结果

[root@aaa1 demo2]$ ansible-playbook 8.yml 
 
PLAY [aaa3] *****************************************************************
 
TASK [Gathering Facts] *********************************************************
ok: [aaa3]
 
PLAY [aaa2] *****************************************************************
 
TASK [Gathering Facts] *********************************************************
ok: [aaa2]
 
TASK [打印rhel803的IP地址] **********************************************************
ok: [aaa2] => {
    "msg": "192.168.56.217"
}
 
PLAY RECAP *********************************************************************
aaa2                    : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
rhel803                    : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
 
[root@aaa1 demo2]

你可能感兴趣的:(Red,hat红帽操作系统,linux,运维,服务器)