ansible变量的使用

本章主要介绍playbook中的变量

  • 自定义变量
  • 使用变量文件
  • 字典变量
  • 列表变量
  • facts变量
  • 内置变量
  • 变量的过滤器
        为了能够写出更实用的playbook,需要在playbook中使用变量。下面来讲解playbook 中常见的变量。本章实验都在/home/lduan/demo2下操作,先把 demo2目录创建出来并把ansible.cfg和 hosts拷贝进去,命令如下。
[blab@node01 ~]$ mkdir demo2
[blab@node01 ~]$ cp ansible.cfg hosts demo2/
[blab@node01 ~]$ cd demo2/
[blab@node01 demo2]$ ls
ansible.cfg  hosts
[blab@node01 demo2]$ 

1.自定义变量

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

1 vars :
2 变量 1 : 1
3 变量 2 : 2
4 ...
定义变量时,不可有重复的变量,否则后面定义的变量的值会覆盖前面定义的变量的值, 如下所示。
1 vars :
2 aa : value1
3 bb : value2
4 aa : value3
5 ...
这里aa重复定义了,所以aa的值最终是value3。
引用变量时用 {{变量名}} ,大括号内侧两边是否有空格是无所谓的,如下所示。
1 {{ 变量名 }}
2 {{ 变量名 }}
3 {{ 变量名 }}
4 {{ 变量名 }}
练习:写一个名称为a.yml的playbook,里面定义以下3个变量。
myname1=tom
myname2=tom2
myname3=tom3
然后打印mynamel的值,命令如下。
[blab@node01 demo2]$ cat a.yml 
---
- hosts: node02
  vars:
   myname1: tom1
   myname2: tom2
   myname3: tom3
  tasks:
  - name: 打印某个变量
    debug: msg="变量myname1的值是{{myname1}}"
[blab@node01 demo2]$ 
运行此playbook,命令如下。
[blab@node01 demo2]$ ansible-playbook a.yml 

PLAY [node02] ******************************************************************

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

TASK [打印某个变量] ******************************************************************
ok: [node02] => {
    "msg": "变量myname1的值是tom1"
}

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

[blab@node01 demo2]$
可以看到,打印了myname1的值为 tom1。
定义变量时,同一个变量定义多次,后面定义的生效,修改a.yml的内容如下。
[blab@node01 demo2]$ cat a.yml 
---
- hosts: node02
  vars:
   myname1: tom1
   myname2: tom2
   myname3: tom3
   myname1: tom3        //增加内容
  tasks:
  - name: 打印某个变量
    debug: msg="变量myname1的值是{{myname1}}"
[blab@node01 demo2]
        这里定义了两次 mynamel 这个变量,第一次定义的值为tom1,第二次定义的值为 tom3。下面运行此playbook查看结果,如下所示。
[blab@node01 demo2]$ ansible-playbook a.yml 
[WARNING]: While constructing a mapping from /home/blab/demo2/a.yml, line 4,
column 4, found a duplicate dict key (myname1). Using last defined value only.

PLAY [node02] ******************************************************************

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

TASK [打印某个变量] ******************************************************************
ok: [node02] => {
    "msg": "变量myname1的值是tom3"
}

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

[blab@node01 demo2]$ 
        因为mynamel重复定义了两次,所以运行此playbook时会有提示,意思是变量重复定义了,且后面定义的myname1生效,打印的结果为 tom3。

2.变量文件

        如果定义的变量太多,可以把变量拿出来单独放在一个文件中,然后在playbook中通过 vars_files引用此变量文件,那么就可以直接使用此变量文件中的变量了,就像变量文件中的变量直接在YAML文件中定义似的,这样更方便管理。
例如,创建文件vars.yml,内容如下。
[blab@node01 demo2]$ cat vars.yml 
myv1: aaa
myv2: bbb
myv3: ccc
[blab@node01 demo2]$ 
修改1.yaml 的内容如下。
[blab@node01 demo2]$ cat a.yml 
---
- hosts: node02
  vars_files:        //增加变量
  - vars.yml        //变量嵌套文件
  vars:
   myname1: tom1
   myname2: tom2
   myname3: tom3
   myname1: tom3
  tasks:
  - name: 打印某个变量
    debug: msg="变量myname1的值是{{myname1}}"
  - name: 打印变量myv1的值
    debug: msg="变量myv1的值是{{myv1}}"        //增加嵌套文件的值
[blab@node01 demo2]$
这里通过vars_files来引用变量文件 vars.yml,然后打印变量myv1的值,运行结果如下。
[blab@node01 demo2]$ ansible-playbook a.yml 
[WARNING]: While constructing a mapping from /home/blab/demo2/a.yml, line 6,
column 4, found a duplicate dict key (myname1). Using last defined value only.

PLAY [node02] ******************************************************************

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

TASK [打印某个变量] ******************************************************************
ok: [node02] => {
    "msg": "变量myname1的值是tom3"
}

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

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

[blab@node01 demo2]$ 

3.字典变量

        所谓字典(dictionaries简写为dict),就是存储多个变量的容器,可以把字典理解为一个木桶,里面存放了很多个变量。如图31-1所示,两个木桶xx和yy,里面分别存储了3个变量: aa=1 bb=2, cc=3。
同一个字典中定义的多个变量不可有重复值,否则后面定义的变量会覆盖前面定义的变量。
要是引用木桶中的变量,必须指定是哪个木桶中的变量。例如,要引用木桶xx中的变量 aa,则使用xx.aa。
字典是在vars下定义的,语法如下。
1 字典名 :
2 var1 : value2
3 var2 : value2
4 ...
注意 : 在字典中定义这一个个变量时,变量前面是不加“-”的,且定义变量没有先后顺序。
通过“字典名.变量名”这种格式来引用变量,看下面的例子。
[blab@node01 demo2]$ cat bb.yml 
---
- hosts: node02
  vars:
   dict1:
    myv1: aaa
    myv2: bbb
    myv3: ccc
   dict2:
    myv1: 111
    myv2: 222
    myv3: 333
  tasks:
  - name: 打印第一个变量
    debug: msg="{{dict1.myv1}}"
[blab@node01 demo2]$ 
        这里定义了两个字典dict1和 dict2,里面分别有3个变量,最后通过dict1.myvl引用了字典dick1中的变量myv1。通过ansible-playbook bb.yml运行的结果应该为aaa,
[blab@node01 demo2]$ ansible-playbook bb.yml 

PLAY [node02] ******************************************************************

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

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

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

[blab@node01 demo2]$ 
如果在同一个字典中出现了相同的变量名,则后面定义的变量的值会覆盖前面定义的变量的值。

4.列表变量

        列表变量和字典变量比较容易弄混。下面来看一个例子,定义一个员工表,里面有3个员工,每个员工通过以下3个属性记录。
  1. uname:记录用户名
  2. age:记录年龄
  3. sex:记录性别
这个员工表的内容如下:
employee:
 uname: lisi
 age: 22
 sex: man
 
 uname: wangwu
 age: 19
 sex: man
 
 uname: xiaohua
 age: 20
 sex: wuman
        为了看得清楚,这里把每个用户用空白行隔开了。每个用户都是由3个变量组成的一个整体,这个整体是员工表employee的一个元素。所以,这个员工表有3个元素,即3个人。
        每个元素都有uname,所以列表employee共有3个uname,但是这3个uname不应该是冲突的,因为它们分别属于不同的人。
        但是为了防止误会,每个元素的第一个变量前都加上一个“-”,表示它是这个元素的第一个变量。所以,员工表改成如下内容。
employee:
 - uname: lisi
   age: 22
   sex: man
 
 - uname: wangwu
   age: 19
   sex: man
 
 - uname: xiaohua
   age: 20
   sex: wuman
这样看起来就清晰了很多,这里employee就是一个列表。
        那如果想获取某个元素(某个员工)的信息该怎么办呢?可以通过employee[n]来获取,这里的n叫作下标,下标从0开始。
例如,要获取第一个用户的信息,则使用employee[0]即可,employee[0]得到的值如下。
 uname: lisi
 age: 22
 sex: man
        可以看到,这是由3个变量组成的,这3个变量组成了一个字典,即employee[0]就是一个字典。如果想获取第一个用户的用户名,则可以通过employee[0].uname来获取。
        所以,员工表employee是由3个字典组成的;employee[0]、employee[1],employee[2]。
列表和字典的不同如下:
(1)列表的每个元素的第一个变量都是以“-”开头。
(2)字典的每个变量前面都不带“-”。
练习1:写一个名称为3-list.yaml 的playbook,定义一个用户列表,里面包含3个用户,每个用户由uname、sex、age组成,命令如下
[blab@node01 demo2]$ cat cc.yml 
---
- hosts: node02
  vars:
   users:
   - uname: tom
     sex: man
     age: 19
   - uname: bob
     sex: man
     agx: 20
   - uname: mary
     sex: women
     age: 18
  tasks:
  - name: 打印一个变量
    debug: msg={{users.2}}
[blab@node01 demo2]$
这里列表users定义了3个元素,现在要获取第3个元素用users[2]来表示,运行结果如下。
[blab@node01 demo2]$ ansible-playbook cc.yml 

PLAY [node02] ******************************************************************

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

TASK [打印一个变量] ******************************************************************
ok: [node02] => {
    "msg": {
        "age": 18,
        "sex": "women",
        "uname": "mary"
    }
}

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

[blab@node01 demo2]$
如果要获取第3个用户的用户名,修改cc.yml的内容如下。
[blab@node01 demo2]$ cat cc.yml 
---
- hosts: node02
  vars:
   users:
   - uname: tom
     sex: man
     age: 19
   - uname: bob
     sex: man
     agx: 20
   - uname: mary
     sex: women
     age: 18
  tasks:
  - name: 打印一个变量
    debug: msg={{users.2.uname}}    //增加uname
[blab@node01 demo2]$
运行此playbook,命令如下
[blab@node01 demo2]$ ansible-playbook cc.yml 

PLAY [node02] ******************************************************************

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

TASK [打印一个变量] ******************************************************************
ok: [node02] => {
    "msg": "mary"
}

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

[blab@node01 demo2]$ 
定义列表时,也可以直接写值不写变量,通过如下方式来定义。
1 listname :
2 var1
3 var2
4 var3
5 ...
这种定义变量的方式可以换成如下内容。
 listname: [var1,var2,var3,...]

5.数字变量的运算

        在YAML 文件中定义的变量,其值如果是数字,则可以进行数学运算。常见的数学运算符包括+(加)、-(减)、*(乘)、/(除)、**(次方)。
练习:写一个名称为4-vars,yaml 的 playbook,定义了变量aa,值为3,然后求aa*2和 aa的3次方
[blab@node01 demo2]$ cat dd.yml 
---
- hosts: node02
  vars:
   aa: 3
  tasks:
  - name: 3*2的值
    debug: msg={{aa*2}}
  - name: 3的3次方
    debug: msg={{3**3}}
[blab@node01 demo2]$ 
运行此playbook
[blab@node01 demo2]$ ansible-playbook dd.yml 

PLAY [node02] ******************************************************************

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

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

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

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

[blab@node01 demo2]$

6.注册变量

        在playbook中用shell模块执行某个系统命令后,在结果中是不会显示这个命令结果的,这个和在命令行中用ansible命令调用shell模块不一样。
练习:写一个 playbook,在里面执行系统命令hostname
[blab@node01 demo2]$ cat ee.yml 
---
- hosts: node02
  tasks:
  - name: 执行一个操作系统命令
    shell: 'hostname'
[blab@node01 demo2]$ 
运行此playbook,命令如下。
[blab@node01 demo2]$ ansible-playbook ee.yml 

PLAY [node02] ******************************************************************

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

TASK [执行一个操作系统命令] **************************************************************
changed: [node02]

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

[blab@node01 demo2]$
        可以看到,没有任何输出。如果想查看这个shell命令的结果,可以把shell 命令的结果保存在一个变量中,这个变量就是注册变量,然后打印这个变量的值即可。修改ee.yml的内容如下。
[blab@node01 demo2]$ cat ee.yml 
---
- hosts: node02
  tasks:
  - name: 执行一个操作系统命令
    shell: 'hostname'
    register: aa
  - name: 打印注册变量aa的值
    debug: msg={{aa}}
[blab@node01 demo2]$ 
运行此playbook
[blab@node01 demo2]$ ansible-playbook ee.yml 

PLAY [node02] ******************************************************************

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

TASK [执行一个操作系统命令] **************************************************************
changed: [node02]

TASK [打印注册变量aa的值] **************************************************************
ok: [node02] => {
    "msg": {
        "changed": true,
        "cmd": "hostname",
        "delta": "0:00:00.002749",
        "end": "2023-12-21 12:02:47.875633",
        "failed": false,
        "rc": 0,
        "start": "2023-12-21 12:02:47.872884",
        "stderr": "",
        "stderr_lines": [],
        "stdout": "node02",
        "stdout_lines": [
            "node02"
        ]
    }
}

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

[blab@node01 demo2]$ 
        结果中msg后面的内容就是aa的值,可以看到aa就是一个字典。其中cmd是执行的系统命令,rc是此命令的返回值,stdout表示此命令的结果。
        所以,如果只获取这个命令的结果,只要打印字典aa中的 stdout 变量即可。修改ee.yml的内容如下。
[blab@node01 demo2]$ cat ee.yml 
---
- hosts: node02
  tasks:
  - name: 执行一个操作系统命令
    shell: 'hostname'
    register: aa
  - name: 打印注册变量aa的值
    debug: msg={{aa.stdout}}    //增加stdout
[blab@node01 demo2]$ 
运行此playbook
[blab@node01 demo2]$ ansible-playbook ee.yml 

PLAY [node02] ******************************************************************

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

TASK [执行一个操作系统命令] **************************************************************
changed: [node02]

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

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

[blab@node01 demo2]$

7.facts变量

        ansible通过setup模块是可以获取到被管理主机的所有信息的,这些信息都是以变量的方式存在,这些变量称为facts,前面在setup模块中已经介绍过了。现在写一个名称为ff.yml的playbook,用于打印node02的IP和主机名,命令如下。
[blab@node01 demo2]$ cat ff.yml 
---
- hosts: node02
  vars:
   list1: ['aaa: ']
  tasks:
  - name: 打印IP
    debug: msg={{ansible_default_ipv4.address}}
  - name: 打印主机名
    debug: msg={{ansible_fqdn}}
[blab@node01 demo2]$
        这里打印 IP 用到的fact变量是 ansible default ipv4.address,打印主机名用到的fact变量是 ansible_fqdn,运行结果如下。
[blab@node01 demo2]$ ansible-playbook ff.yml 

PLAY [node02] ******************************************************************

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

TASK [打印IP] ********************************************************************
ok: [node02] => {
    "msg": "192.168.182.193"
}

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

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

[blab@node01 demo2]$ 
这里显示 node02的 IP 是192.168.182.193,主机名是node02。

8.内置变量 groups

        在 ansible 中,除用户手动去定义一些变量外,还有一些内置的变量,这些变量不需要用户定义就可以直接使用。
groups用于列出清单文件中所有定义的主机组及里面的主机,看下面的例子。
[blab@node01 demo2]$ cat gg.yml 
---
- hosts: node02
  tasks:
  - name: xxx
    debug: msg={{groups}}
[blab@node01 demo2]$ 
运行此playbook,命令如下。
[blab@node01 demo2]$ ansible-playbook gg.yml 

PLAY [node02] ******************************************************************

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

TASK [xxx] *********************************************************************
ok: [node02] => {
    "msg": {
        "all": [
            "node02",
            "node04",
            "node03"
        ],
        "db": [
            "node02",
            "node03"
        ],
        "db1": [
            "node02",
            "node04"
        ],
        "ungrouped": []
    }
}

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

[blab@node01 demo2]$
这里显示了清单文件中所有的主机组及里面的主机信息
        如果只想列出某个主机组,可以通过“groups['主机组名]”或“groups.主机组名”来表示。修改gg.yml的内容如下。

[blab@node01 demo2]$ cat gg.yml 
---
- hosts: node02
  tasks:
  - name: xxx
    debug: msg={{groups.db}}    //增加内容.db
[blab@node01 demo2]$ 
这里只显示主机组db中的主机,运行结果如下。
[blab@node01 demo2]$ ansible-playbook gg.yml 

PLAY [node02] ******************************************************************

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

TASK [xxx] *********************************************************************
ok: [node02] => {
    "msg": [
        "node02",
        "node03"
    ]
}

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

[blab@node01 demo2]$
可以看到,这里只显示了db 主机组中的主机。
groups.db可以改写成 groups['db'],如下所示。

[blab@node01 demo2]$ cat gg.yml 
---
- hosts: node02
  tasks:
  - name: xxx
    debug: msg={{groups['db']}}
[blab@node01 demo2]$

9.内置变量hostvars

hostvars用来显示指定主机的 fact变量,用法如下
hostvars [ ' 主机名 ' ]. 键值
        此变量一般用于,当某个play的 hosts 中只写了A主机组,但是同时想在此play中显示B主机组中的信息,这时可以选择此变量。
练习:写一个playbook,里面包含一个play,里面的hosts指定为node02,但是要显示node03的IP地址,命令如下。
[blab@node01 demo2]$ cat hh-hostvars.yml 
---
- hosts: node02
  tasks:
  - name: 打印node03的ip
    debug: msg={{hostvars.node03.ansible_default_ipv4.address}}
[blab@node01 demo2]$
运行此playbook
[blab@node01 demo2]$ ansible-playbook hh-hostvars.yml 

PLAY [node02] ******************************************************************

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

TASK [打印node03的ip] *************************************************************
fatal: [node02]: FAILED! => {"msg": "The task includes an option with an undefined variable. The error was: 'ansible.vars.hostvars.HostVarsVars object' has no attribute 'ansible_default_ipv4'\n\nThe error appears to be in '/home/blab/demo2/hh-hostvars.yml': line 4, column 5, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n  tasks:\n  - name: 打印node03的ip\n    ^ here\n"}

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

[blab@node01 demo2]$ 
        这里却出现了报错,这是因为play 的hosts中只写了node02,所以只会获取node02的 fact 变量,并不会获取node03的fact变量,也就不会识别node03上的ansible_default_ipv4.address。
修改hh-hostvars.yml的内容如下
[blab@node01 demo2]$ cat hh-hostvars.yml 
---
- hosts: node03

- hosts: node02
  tasks:
  - name: 打印node03的ip
    debug: msg={{hostvars.node03.ansible_default_ipv4.address}}
[blab@node01 demo2]$
        这里只比前面多了一个play,且这个play中只写了一个 hosts: node03。但是这一句就可以获取到node3的 fact变量,这样在第二个play中再次获取node03的fact变量时就不会报错了。
运行结果如下。
[blab@node01 demo2]$ ansible-playbook hh-hostvars.yml 

PLAY [node03] ******************************************************************

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

PLAY [node02] ******************************************************************

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

TASK [打印node03的ip] *************************************************************
ok: [node02] => {
    "msg": "192.168.182.210"
}

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

[blab@node01 demo2]$ 
可以看到,此处已经正确地获取到 node03的IP了。

10.内置变量inventory hostname

        当ansible主机同时在多台被管理主机上执行任务时,每台被管理主机都会有一个变量记录它在清单文件中的名称是什么,如图31-2所示。
这个变量就是inventory _hostname,记录了每个主机在清单文件中的名称。
练习:写一个playbook,在主机组db上执行,命令如下。
[blab@node01 demo2]$ cat 9-inventory.yml 
---
- hosts: db
  tasks:
  - name: 打印我在清单文件中的名称
    debug: msg={{inventory_hostname}}
[blab@node01 demo2]$
        这里playbook 会在db主机组上执行,即在node02和 node03上执行。在node2上执行时inventory_hostname的值为node02,在node03上执行时 inventory_hostname的值为node03,运行结果如下。
[blab@node01 demo2]$ ansible-playbook 9-inventory.yml 

PLAY [db] **********************************************************************

TASK [Gathering Facts] *********************************************************
ok: [node03]
ok: [node02]

TASK [打印我在清单文件中的名称] ************************************************************
ok: [node02] => {
    "msg": "node02"
}
ok: [node03] => {
    "msg": "node03"
}

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

[blab@node01 demo2]$
        上面的例子中,hosts 的值写的是 db,所以后续的task是要在node02和 node03上同时执行的。修改清单文件 hosts,添加一个主机组xx,里面的主机包括server2这一台主机。
[blab@node01 demo2]$ cat hosts 
node02
node03

[db]
node02
node03

[xx]        //增加的主机组
node02
[blab@node01 demo2]$
修改9-inventory1.yml的内容如下。
[blab@node01 demo2]$ cat 9-inventory.yml 
---
- hosts: db
  tasks:
  - name: 打印我在清单文件中的名称
    debug: msg={{inventory_hostname}}
    when: inventory_hostname in groups ['xx']    //增加内容
[blab@node01 demo2]$
        这里增加了一条判断语句when(后面会专门讲解),执行debug模块的条件是被管理主机要属于xx主机组。虽然 hosts后面跟的是db,node03在db主机组但没有在xx主机组中,条件不满足,所以在 node03上并不执行debug模块。运行结果如下。
[blab@node01 demo2]$ ansible-playbook 9-inventory.yml 

PLAY [db] **********************************************************************

TASK [Gathering Facts] *********************************************************
ok: [node03]
ok: [node02]

TASK [打印我在清单文件中的名称] ************************************************************
ok: [node02] => {
    "msg": "node02"
}
skipping: [node03]

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

[blab@node01 demo2]$
这里跳过了node03,只有ndoe02执行了debug模块。

11.变量的过滤器

        所谓变量的过滤器,实际上就是对变量的值进行一些操作,例如,进行类型转化、截取、加密等操作,使用格式如下
{{ 变量名 | 函数 }}
练习:把大写字符转换成小写字符,命令如下。
[blab@node01 demo2]$ cat 10-vars1.yml 
---
- hosts: node02
  vars:
   aa: tom
   bb: BOB
  tasks:
  - name: xxx
    debug: msg={{bb | lower}}
[blab@node01 demo2]$
        这里定义了一个变量bb值为大写的 BOB,通过 lower这个过滤器会把大写字符转换成小写字符。运行此playbook,命令如下。

[blab@node01 demo2]$ ansible-playbook 10-vars1.yml 

PLAY [node02] ******************************************************************

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

TASK [xxx] *********************************************************************
ok: [node02] => {
    "msg": "bob"
}

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

[blab@node01 demo2]$
可以看到,这里显示的是小写的bob。

下面列出几个常见的过滤器。

11.1.数字类型

整型int,可以把字符串转换成整型,看下面的例子。
[blab@node01 demo2]$ cat 10-vars2.yml 
---
- hosts: node02
  tasks:
  - name: 数学运算
    debug: msg:{{3+'3'}}
[blab@node01 demo2]$
        这里对3+'3'进行数学运算,但是第二个3用单引号引起来了,说明是一个字符串,用数字3和字符串3相加是要报错的,运行结果如下。
[blab@node01 demo2]$ ansible-playbook 10-vars2.yml 

PLAY [node02] ******************************************************************

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

TASK [数学运算] ********************************************************************
fatal: [node02]: FAILED! => {"msg": "Unexpected templating type error occurred on (msg:{{3+'3'}}): unsupported operand type(s) for +: 'int' and 'str'"}

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

[blab@node01 demo2]$ 
        这里报错的提示信息的意思是,数字不能和字符串进行数学运算。我们可以把字符串'3'通过int转换成数字,修改10-vars2.yml的内容如下。
[blab@node01 demo2]$ cat 10-vars2.yml 
---
- hosts: node02
  tasks:
  - name: 数学运算
    debug: msg={{3+('3'|int)}}
[blab@node01 demo2]$ 
其中'3'通过管道传递给int,转换成整型类型的,这样就可以相加了,运行结果如下。
[blab@node01 demo2]$ ansible-playbook 10-vars2.yml 

PLAY [node02] ******************************************************************

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

TASK [数学运算] ********************************************************************
ok: [node02] => {
    "msg": "6"
}

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

[blab@node01 demo2]$
2.浮点型float,可以把字符串转换成小数类型的数字,修改10-vars2.yaml的内容如下。
[blab@node01 demo2]$ cat 10-vars2.yml 
---
- hosts: node02
  tasks:
  - name: 数学运算
    debug: msg={{3+('3'|float)}}
[blab@node01 demo2]$ 
这里用float把'3'转换成浮点型,即 3.0,运行结果如下。
[blab@node01 demo2]$ ansible-playbook 10-vars2.yml 

PLAY [node02] ******************************************************************

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

TASK [数学运算] ********************************************************************
ok: [node02] => {
    "msg": "6.0"
}

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

[blab@node01 demo2]$ 
3.绝对值abs,可以把负数转换成正数,如-3变成3,修改10-vars2.yaml的内容如下。
[blab@node01 demo2]$ cat 10-vars2.yml 
---
- hosts: node02
  tasks:
  - name: 数学运算
    debug: msg={{-3 | abs}}
[blab@node01 demo2]$
这里用abs求-3的绝对值,得到的值应该是3,运行结果如下。
[blab@node01 demo2]$ ansible-playbook 10-vars2.yml 

PLAY [node02] ******************************************************************

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

TASK [数学运算] ********************************************************************
ok: [node02] => {
    "msg": "3"
}

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

[blab@node01 demo2]$

11.2列表

前面讲过一个列表中可以包括多个值,列表的过滤器可以求出列表的长度、最大值、最小值等。
  1. length:用于求列表的长度
  2. max:用于求列表中的最大值
  3. min:用于求列表中的最小值
练习:写一个 playbook,内容如下。
[blab@node01 demo2]$ cat 10-vars3.yml 
---
- hosts: node02
  vars:
   list1: [1,2,8,3,2]
  tasks:
  - name: 求列表长度
    debug: msg="{{list1 | length}}"
  - name: 求列表中的最大值
    debug: msg="{{list1 | max}}"
  - name: 求列表中的最小值
    debug: msg="{{list1 | min}}"
[blab@node01 demo2]$ 
这里定义了一个列表list1,然后分别求列表的长度、最大值、最小值,运行结果如下。
[blab@node01 demo2]$ ansible-playbook 10-vars3.yml 

PLAY [node02] ******************************************************************

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

TASK [求列表长度] *******************************************************************
ok: [node02] => {
    "msg": "5"
}

TASK [求列表中的最大值] ****************************************************************
ok: [node02] => {
    "msg": "8"
}

TASK [求列表中的最小值] ****************************************************************
ok: [node02] => {
    "msg": "1"
}

PLAY RECAP *********************************************************************
node02                     : ok=4    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

[blab@node01 demo2]$
        可以看到,列表的长度为5,说明列表中有5个元素,最大值为8,最小值为1。用于列表的过滤器还包括sort(排序)、sum(求和)、shuffle(打乱顺序显示)等。

11.3设置默认值default

如果某个变量没有被定义,那么可以通过default给它设置一个默认值,用法如下。

{{ var1 | default(value1) }}

如果某个变量var1已经定义了,则显示它自己的值;如果没有被定义,则被赋值为value1.
练习:写一个playbook,内容如下。
[blab@node01 demo2]$ cat 10-vars4.yml 
---
- hosts: node02
  vars:
   aa: 11
   bb: 
  tasks:
  - name: aa的值
    debug: msg="{{aa | default('xxx')}}"
  - name: bb的值
    debug: msg="{{bb | default('xxx')}}"
  - name: cc的值
    debug: msg="{{cc | default('xxx')}}"
[blab@node01 demo2]$
        这里定义了aa的值为11,定义了bb但是没有赋值,并没有定义cc。所以,打印aa时,会显示自己的值即11;打印bb时,会显示自己的值即空值;打印 cc时,显示的是default中的值即xxx。运行结果如下。
[blab@node01 demo2]$ ansible-playbook 10-vars4.yml 

PLAY [node02] ******************************************************************

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

TASK [aa的值] ********************************************************************
ok: [node02] => {
    "msg": "11"
}

TASK [bb的值] ********************************************************************
ok: [node02] => {
    "msg": ""
}

TASK [cc的值] ********************************************************************
ok: [node02] => {
    "msg": "xxx"
}

PLAY RECAP *********************************************************************
node02                     : ok=4    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

[blab@node01 demo2]$

11.4字符串相关

string能把其他数据类型转换成字符串,看下面的例子。
[blab@node01 demo2]$ cat 10-vars5.yml 
---
- hosts: node02
  tasks:
  - name: 求和
    debug: msg="{{3+3|string}}"
[blab@node01 demo2]$
        3+3本身是可以正常运行的,但这里通过3string把第二个3转换成了字符串,因为数字只能和数字相加,所以上述执行数字3和字符串3相加会报错,运行结果如下。
[blab@node01 demo2]$ ansible-playbook 10-vars5.yml 

PLAY [node02] ******************************************************************

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

TASK [求和] **********************************************************************
fatal: [node02]: FAILED! => {"msg": "Unexpected templating type error occurred on ({{3+3|string}}): unsupported operand type(s) for +: 'int' and 'str'"}

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

[blab@node01 demo2]$ 

这个用法其实和前面的3+3'是类似的,单引号也可以转换成字符串。

capitalize过滤器用于把字符串的首字符转换成大写,看下面的例子。
[blab@node01 demo2]$ cat 10-vars6.yml 
---
- hosts: node02
  tasks:
  - name: 字符串集
    debug: msg="{{'aa' | capitalize}}"
[blab@node01 demo2]$
运行此playbook,命令如下。
[blab@node01 demo2]$ ansible-playbook 10-vars6.yml 

PLAY [node02] ******************************************************************

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

TASK [字符串集] ********************************************************************
ok: [node02] => {
    "msg": "Aa"
}

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

[blab@node01 demo2]$ 

可以看到,aa通过capitalize过滤器转换之后,首字符变成了大写。

        关于字符的过滤器还有upper(把小写字符转换成大写)、lower(把大写字符转换成小写),这些请大家自行练习。

11.5加密相关

        有时需要对字符串进行加密操作,例如,在创建用户时给用户设置密码,就要用密文的形式而不能用明文。
求哈希值hash,算法可以是md5 或sha等,用法如下。
hash ( ' 算法名 ' )
练习1:写一个 playbook,对字符串 haha001实现不同的加密,命令如下。
[blab@node01 demo2]$ cat 10-vars7.yml 
---
- hosts: node02
  vars:
   password: aaa001
  tasks:
  - name: 用md5加密
    debug: msg={{password | hash('md5')}}
  - name: 用sha1加密
    debug: msg={{password | hash('sha1')}}
  - name: 用sha512加密
    debug: msg={{password | hash('sha512')}}
[blab@node01 demo2]$ 
        这里定义了一个变量 passa=haha001,然后分别使用md5、sha1、sha512对它进行加密,运行结果如下
[blab@node01 demo2]$ ansible-playbook 10-vars7.yml 

PLAY [node02] ******************************************************************

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

TASK [用md5加密] ******************************************************************
ok: [node02] => {
    "msg": "ba5cbfec1ff34168f1ab08e19fd397b0"
}

TASK [用sha1加密] *****************************************************************
ok: [node02] => {
    "msg": "189d05ec2089c54128700410b76168bb0bea9be8"
}

TASK [用sha512加密] ***************************************************************
ok: [node02] => {
    "msg": "47bb39c0066fad64c31187030979d822b984c6f5fd6acf5db401b914fe69d279c7229f33c7485cfa1c00de6fa0fea36ee87e6c39aa3ba0a29edadb070be71d72"
}

PLAY RECAP *********************************************************************
node02                     : ok=4    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

[blab@node01 demo2]$ 
注意: hash过滤器中的md5或sha要用单引号引起来
password_hash ( ' 算法名 ' )
在 Linux系统中,用户密码一般使用的是sha512加密算法,所以一般用 password_hash('sha512')给用户的密码加密。
修改10-vars7.yaml的内容如下。
[blab@node01 demo2]$ cat 10-vars7.yml 
---
- hosts: node02
  vars:
   password: aaa001
  tasks:
  - name: 用md5加密
    debug: msg={{password | password_hash('md5')}}    //修改内容
[blab@node01 demo2]$ 
这里调用sha512对变量 password 的值(就是 aaa001)进行加密,运行结果如下。
[blab@node01 demo2]$ ansible-playbook 10-vars7.yml 

PLAY [node02] ******************************************************************

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

TASK [用md5加密] ******************************************************************
ok: [node02] => {
    "msg": "$1$.JFajmN6$pg5Bkp9E.jqvN1abNghW1/"
}

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

[blab@node01 demo2]$
注意 : password_hash过滤器中的sha512要用单引号引起来。
练习2:在server2上创建用户bob,并设置密码为haha001。
先确定node02上不存在bob用户,命令如下。
[blab@node01 demo2]$ ansible node02 -m shell -a "id bob"
node02 | FAILED | rc=1 >>
id: “bob”:无此用户non-zero return code
[blab@node01 demo2]$
然后开始写playbook,内容如下。
[blab@node01 demo2]$ cat 10-vars8.yml 
---
- hosts: node02
  vars:
   password: aaa001
  tasks:
  - name: 创建一个bob用户
    user: user=bob comment="Im bob" groups=root password={{password | password_hash('sha512')}}
[blab@node01 demo2]$ 
        这里调用user模块,name指定用户名为bob,comment用于指定用户的描述信息,password用于指定密码。
运行此 playbook
[blab@node01 demo2]$ ansible-playbook 10-vars8.yml 

PLAY [node02] ******************************************************************

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

TASK [创建一个bob用户] ***************************************************************
changed: [node02]

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

[blab@node01 demo2]$
验证,切换到node02上
[blab@node01 demo2]$ ansible node02 -m shell -a "id bob"
node02 | CHANGED | rc=0 >>
uid=1003(bob) gid=1003(bob) 组=1003(bob),0(root)
[blab@node01 demo2]$
        这里先从 root切换到tom用户,因为root切换到其他任何用户都不需要密码。从tom用户用su命令切换到bob用户时需要输入密码 haha001,证明bob用户已经创建成功且密码也是正确的。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/261219.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【高录用快检索】第四届机械设计与仿真国际学术会议(MDS 2024)

【高录用快检索】第四届机械设计与仿真国际学术会议(MDS 2024) 2024 4th International Conference on Mechanical Design and Simulation 2024年第四届机械设计与仿真国际学术会议(MDS 2024) 将于2024年03月01-03日在中国西安召开。MDS 2024将围绕“…

一篇文章带你了解SpringBoot目录结构

前言 SpringBoot是整合Spring技术栈的一站式框架,是简化Spring技术栈的快速开发脚手架,是一个能够快速构建生产级别的Spring应用的工具。SpringBoot是目前流行的微服务框架,倡导“约定优于配置”,简化Spring项目搭建及开发过程。…

Ubuntu配置GPU资源

0、升级内核为5.15.0-88-generic: 0.1 配置下载源: 在/etc/apt/sources.list.d目录下新建list文件,添加内容: deb http://mirrors.aliyun.com/ubuntu/ focal-updates amin restricted0.2 下载 sudo apt-get install linux-imag…

中小型教育网络安全解决方案

热门IT技术视频教程:https://xmws-it.blog.csdn.net/article/details/134398330?spm1001.2014.3001.5502 一、中小型教育网络的安全现状及挑战 当前,校园网的安全形势非常严峻,大量的垃圾邮件、黑客攻击、病毒蠕虫等困扰着管理者。而且这些作…

java使用面向对象实现图书管理系统

꒰˃͈꒵˂͈꒱ write in front ꒰˃͈꒵˂͈꒱ ʕ̯•͡˔•̯᷅ʔ大家好,我是xiaoxie.希望你看完之后,有不足之处请多多谅解,让我们一起共同进步૮₍❀ᴗ͈ . ᴗ͈ აxiaoxieʕ̯•͡˔•̯᷅ʔ—CSDN博客 本文由xiaoxieʕ̯•͡˔•̯᷅ʔ 原创 CSDN …

2023年12月21日历史上的今天大事件早读

1375年12月21日 意大利文艺复兴的代表人物薄伽丘逝世 1620年12月21日 英国抵达第一个北美殖民地普利茅斯 1879年12月21日 斯大林出生 1921年12月21日 苏俄电气化计划批准 1928年12月21日 天津劝业场开业 1928年12月21日 中国核化学家王方定出生 1935年12月21日 载客21人的…

飞书+ChatGPT搭建智能AI助手,无公网ip实现公网访问飞书聊天界面

飞书ChatGPT搭建智能AI助手,无公网ip实现公网访问飞书聊天界面 前言环境列表1.飞书设置2.克隆feishu-chatgpt项目3.配置config.yaml文件4.运行feishu-chatgpt项目5.安装cpolar内网穿透6.固定公网地址7.机器人权限配置8.创建版本9.创建测试企业10. 机器人测试 前言 …

qt-C++笔记之app.processEvents()和QApplication::processEvents()的区别

qt-C笔记之app.processEvents()和QApplication::processEvents()的区别 code review! 代码1: QApplication app(argc, argv); app.processEvents(); 代码2: QApplication::processEvents(); 区别 代码1和代码2的区别在于代码1中使用了一个具体的QApplication对…

Java项目的学习记录---12306购票系统的技术架构选型

后端技术架构 选择基于 Spring Boot 3 和 JDK17 进行底层建设 前端技术架构

征集倒计时 | 2023年卓越影响力榜单-第四届中国产业创新奖报名即将截止

第四届「ISIG中国产业智能大会」将于2024年3月16日在上海举办。2024 ISIG 以“与科技共赢,与产业共进”为主题,共设立RPA超自动化、 低代码、AIGC大模型、流程挖掘四大主题峰会。届时,大会组委会将颁发2023年度卓越影响力榜单—第四届中国产业…

动态内存分配(malloc和free​、calloc和realloc​)

目录 一、为什么要有动态内存分配​ 二、C/C中程序内存区域划分​ 三、malloc和free​ 2.1、malloc 2.2、free​ 四、calloc和realloc​ 3.1、calloc​ 3.2、realloc​ 3.3realloc在调整内存空间的是存在两种情况: 3.4realloc有malloc的功能 五、常见的动…

vue proxy代理 和 Nginx 配置跨域

vue.config.js文件中配置的代理: devServer: {port: 9095,// open: true, // 配置项目在启动时自动在浏览器打开proxy: {/yh: { // /api是代理标识,一般是每个接口前的相同部分target: "http://192.168.5.58:8002", // 请求地址,一…

Python3 标准库中推荐的命令行解析模块argparse的使用示例

import os import argparse import sys import requests import json import subprocess from datetime import datetime# 定义一个装饰器,在方法执行异常时跳过执行 def skip_on_exception(func):def wrapper(*args, **kwargs):try:return func(*args, **kwargs)ex…

uniapp uview 页面多个select组件回显处理,默认选中

<view class"add-item column space-around" click"selectClick(1)"><text class"w-s-color-3 f-28">商品分类</text><view class"w-100 space-between"><!-- 第一个参数为你的单选数组&#xff0c;第二个…

黑马头条--day07--app文章搜索

目录 一.安装elasticsearch 1.拉取镜像 2.创建存放数据及配置文件的文件夹&#xff0c;启动时挂载。 4.修改文件夹权限 5.启动容器 5.1参数解释 6.安装ik分词器 6.2测试一下Ik分词器 二.添加文章索引库 1查询所有的文章信息&#xff0c;批量导入到es索引库中 2)测试 …

自我学习--关于如何设计光耦电路

本人在项目中多次设计光耦电路&#xff0c;目前电路在项目中运行比较平稳&#xff0c;所以总结一下自己的设计经验&#xff0c;与大家交流一下&#xff0c;如有错误还希望大家指出改正&#xff0c;谢谢&#xff08;V&#xff1a;Smt15921588263&#xff1b;愿与大家多交流&…

红队打靶练习:DIGITALWORLD.LOCAL: DEVELOPMENT

信息收集 1、arp ┌──(root㉿ru)-[~/kali] └─# arp-scan -l Interface: eth0, type: EN10MB, MAC: 00:0c:29:69:c7:bf, IPv4: 192.168.12.128 Starting arp-scan 1.10.0 with 256 hosts (https://github.com/royhills/arp-scan) 192.168.12.1 00:50:56:c0:00:08 …

持续集成交付CICD:Jenkins使用GitLab共享库实现前端项目镜像构建

目录 一、实验 1. GitLab修改项目文件与Harbor环境确认 2.Jenkins使用GitLab共享库实现前端项目镜像构建 3.优化CI流水线封装Harbor账户密码 4.Jenkins再次使用GitLab共享库实现前端项目镜像构建 一、实验 1. GitLab修改项目文件与Harbor环境确认 &#xff08;1&#xf…

多维时序 | MATLAB实现BiTCN-Multihead-Attention多头注意力机制多变量时间序列预测

多维时序 | MATLAB实现BiTCN-Multihead-Attention多头注意力机制多变量时间序列预测 目录 多维时序 | MATLAB实现BiTCN-Multihead-Attention多头注意力机制多变量时间序列预测预测效果基本介绍模型描述程序设计参考资料 预测效果 基本介绍 多维时序 | MATLAB实现BiTCN-Multihea…

cisp和cissp区别,考证必学资料

CISP&#xff08;Certified Information Security Professional&#xff0c;认证信息安全专家&#xff09;和CISSP&#xff08;Certified Information Systems Security Professional&#xff0c;认证信息系统安全专业人员&#xff09;都是信息安全领域的重要认证&#xff0c;但…