Linux变量的使用(2)
1.数字变量的运算
在YAML文件中定义的变量,其如果是数字,则可以进行数字运算。常见的数字运算符包括 +、- 、* - / 、**。
写一个名称为4-vars,yaml 的 playbook,定义了变量aa,值为3,然后求aa*2和aa的3次方,命令如下。
[blab@rh1 demo2]$ cat 4-list.yaml
---
- hosts: rh2
vars:
aa: 3
tasks:
- name: 3乘2的值
debug: msg={{aa*2}}
- name: 3的3次方
debug: msg="{{3**3}}"
运行此playbook,命令如下。
[blab@rh1 demo2]$ ansible-playbook 4-list.yaml
PLAY [rh2] ********************************************************************************************
TASK [Gathering Facts] ********************************************************************************
ok: [rh2]
TASK [3乘2的值] ******************************************************************************************
ok: [rh2] => {
"msg": "6"
}
TASK [3的3次方] ******************************************************************************************
ok: [rh2] => {
"msg": "27"
}
PLAY RECAP ********************************************************************************************
rh2 : ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
2.注册变量
在playbook中用shell模块执行某个系统命令后,在结果中是不会显示这个命令结果的,这个和在命令行中用ansible命令调用shell模块不一样。
写一个 playbook,在里面执行系统命令hostname,命令如下。
[blab@rh1 demo2]$ cat 5-regl.yaml
---
- hosts: rh2
tasks:
- name: 执行一个操作系统命令
shell: 'hostname'
运行此playbook,命令如下。
[blab@rh1 demo2]$ ansible-playbook 5-regl.yaml
PLAY [rh2] ********************************************************************************************
TASK [Gathering Facts] ********************************************************************************
ok: [rh2]
TASK [执行一个操作系统命令] *************************************************************************************
changed: [rh2]
PLAY RECAP ********************************************************************************************
rh2 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
可以看到,没有任何输出。如果想查看这个shell命令的结果,可以把shell 命令的结果保存在一个变量中,这个变量就是注册变量,然后打印这个变量的值即可。修改5-reg1.yaml的内容如下。
[blab@rh1 demo2]$ cat 5-regl.yaml
---
- hosts: rh2
tasks:
- name: 执行一个操作系统命令
shell: 'hostname'
register: aa
- name: 打印aa注册变量的值
debug: msg={{aa}}
运行此playbook,命令如下
[blab@rh1 demo2]$ ansible-playbook 5-regl.yaml
PLAY [rh2] ********************************************************************************************
TASK [Gathering Facts] ********************************************************************************
ok: [rh2]
TASK [执行一个操作系统命令] *************************************************************************************
changed: [rh2]
TASK [打印aa注册变量的值] *************************************************************************************
ok: [rh2] => {
"msg": {
"changed": true,
"cmd": "hostname",
"delta": "0:00:00.003323",
"end": "2023-12-22 10:06:56.331276",
"failed": false,
"rc": 0,
"start": "2023-12-22 10:06:56.327953",
"stderr": "",
"stderr_lines": [],
"stdout": "rh2",
"stdout_lines": [
"rh2"
]
}
}
PLAY RECAP ********************************************************************************************
rh2 : ok=3 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
结果中msg后面的内容就是aa的值,可以看到aa就是一个字典。其中cmd是执行的系统命令,rc是此命令的返回值,stdout表示此命令的结果。
所以,如果只获取这个命令的结果,只要打印字典aa中的 stdout 变量即可。修改5-regl.yam1的内容如下。
[blab@rh1 demo2]$ cat 5-regl.yaml
---
- hosts: rh2
tasks:
- name: 执行一个操作系统命令
shell: 'hostname'
register: aa
- name: 打印aa注册变量的值
debug: msg={{aa.stdout}}
运行此playbook,命令如下
[blab@rh1 demo2]$ ansible-playbook 5-regl.yaml
PLAY [rh2] ********************************************************************************************
TASK [Gathering Facts] ********************************************************************************
ok: [rh2]
TASK [执行一个操作系统命令] *************************************************************************************
changed: [rh2]
TASK [打印aa注册变量的值] *************************************************************************************
ok: [rh2] => {
"msg": "rh2"
}
PLAY RECAP ********************************************************************************************
rh2 : ok=3 changed=1 unreachable=0 failed=0 skipped=0 rescued=0
这里正确的显示了hostname的值为server2.rhcc.cc
3.facts变量
ansible通过setup模块是可以获取到被管理主机的所有信息的,这些信息都是以变量的方式存在,这些变量称为facts,前面在setup模块中已经介绍过了。现在写一个名称为6-fact.yaml的playbook,用于打印server2的IP和主机名,命令如下。
[blab@rh1 demo2]$ cat 6-fact.yaml
---
- hosts: rh2
vars:
list1: ['aaa: ']
tasks:
- name: 打印IP
debug: msg={{ansible_default_ipv4.address}}
- name: 打印主机名
debug: msg={{ansible_fqdn}}
这里打印 IP 用到的fact变量是 ansible default ipv4.address,打印主机名用到的fact变量是 ansible_fqdn,运行结果如下。
[blab@rh1 demo2]$ ansible-playbook 6-fact.yaml
PLAY [rh2] ********************************************************************************************
TASK [Gathering Facts] ********************************************************************************
ok: [rh2]
TASK [打印IP] *******************************************************************************************
ok: [rh2] => {
"msg": "192.168.25.171"
}
TASK [打印主机名] ******************************************************************************************
ok: [rh2] => {
"msg": "rh2"
}
PLAY RECAP ********************************************************************************************
rh2 : ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
这里显示 rh2的 IP 是192.168.25.172,主机名是rh2。
4.内置变量groups
在 ansible 中,除用户手动去定义一些变量外,还有一些内置的变量,这些变量不需要用户定义就可以直接使用。
groups用于列出清单文件中所有定义的主机组及里面的主机,看下面的例子。
[blab@rh1 demo2]$ cat 7-group.yaml
---
- hosts: rh2
tasks:
- name: xxx
debug: msg{{groups}}
运行此playbook,命令如下。
[blab@rh1 demo2]$ ansible-playbook 7-group.yaml
PLAY [rh2] ********************************************************************************************
TASK [Gathering Facts] ********************************************************************************
ok: [rh2]
TASK [xxx] ********************************************************************************************
ok: [rh2] => {
"msg": "Hello world!"
}
PLAY RECAP ********************************************************************************************
rh2 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
这里显示了清单文件中所有的主机组及里面的主机信息。
如果只想列出某个主机组,可以通过“groups['主机组名]”或“groups.主机组名”来表示。修改7-group.yaml的内容如下。
[blab@rh1 demo2]$ cat 7-group.yaml
---
- hosts: rh2
tasks:
- name: xxx
debug: msg{{groups['db']}}
这里只显示主机组db中的主机,运行结果如下。
[blab@rh1 demo2]$ ansible-playbook 7-group.yaml
PLAY [rh2] ********************************************************************************************
TASK [Gathering Facts] ********************************************************************************
ok: [rh2]
TASK [xxx] ********************************************************************************************
ok: [rh2] => {
"msg": "Hello world!"
}
PLAY RECAP ********************************************************************************************
rh2 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
可以看到,这里只显示了db 主机组中的主机。
5.内置变量hostvars
hostvars用来显示指定主机的 fact变量,用法如下。
此变量一般用于,当某个play的 hosts 中只写了A主机组,但是同时想在此play中显示B主机组中的信息,这时可以选择此变量。
写一个playbook,里面包含一个play,里面的hosts指定为rh2,但是要显示rh3的IP地址,命令如下。
[blab@rh1 demo2]$ cat 8-hostvars.yaml
---
- hosts: rh2
tasks:
- name: 打印rh3的IP
debug: msg={{hostvars['rh3'].ansible_default_ipv4.address}}
运行此playbook,命令如下
[blab@rh1 demo2]$ ansible-playbook 8-hostvars.yaml
PLAY [rh2] ********************************************************************************************
TASK [Gathering Facts] ********************************************************************************
ok: [rh2]
TASK [打印rh3的IP] ***************************************************************************************
fatal: [rh2]: 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/8-hostvars.yaml': 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: 打印rh3的IP\n ^ here\n"}
PLAY RECAP ********************************************************************************************
rh2 : ok=1 changed=0 unreachable=0 failed=1 skipped=0 rescued=0 ignored=0
这里却出现了报错,这是因为play 的hosts中只写了rh2,所以只会获取rh2的 fact变量,并不会获取rh3的fact变量,也就不会识别rh3上的ansible_default_ipv4.address。
修改8-hostvars.yaml的内容如下。
[blab@rh1 demo2]$ cat 8-hostvars.yaml
---
- hosts: rh2
- hosts: rh3
tasks:
- name: 打印rh3的IP
debug: msg={{hostvars['rh3'].ansible_default_ipv4.address}}
这里只比前面多了一个play,且这个play中只写了一个 hosts: rh3。但是这一句就可以获取到rh3的 fact变量,这样在第二个play中再次获取rh3的fact变量时就不会报错了。
运行结果如下。
[blab@rh1 demo2]$ ansible-playbook 8-hostvars.yaml
PLAY [rh2] ********************************************************************************************
TASK [Gathering Facts] ********************************************************************************
ok: [rh2]
PLAY [rh3] ********************************************************************************************
TASK [Gathering Facts] ********************************************************************************
ok: [rh3]
TASK [打印rh3的IP] ***************************************************************************************
ok: [rh3] => {
"msg": "192.168.25.172"
}
PLAY RECAP ********************************************************************************************
rh2 : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
rh3 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
可以看到,此处已经正确地获取到 rh3的IP了。