承接前文,这篇文章将继续介绍变量的一些使用方法。

 

注册变量


ansible的模块在运行之后,其实都会返回一些"返回值",只是默认情况下,这些"返回值"并不会显示而已,我们可以把这些返回值写入到某个变量中,这样我们就能够通过引用对应的变量从而获取到这些返回值了,这种将模块的返回值写入到变量中的方法被称为"注册变量",那么怎样将返回值注册到变量中呢?我们来看一个playbook示例

---
- hosts: test70
remote_user: root
tasks:
- name: test shell
shell: "echo test > /var/testshellfile"
register: testvar
- name: shell module return values
debug:
var: testvar

上例中共有两个任务,第一个任务使用shell模块在test70主机中创建了一个测试文件 /var/testshellfile,将字符"test"输入到了测试文件中,然后使用"register"关键字将当前shell任务的返回值写入了名为"testvar"的变量中,第二个任务使用debug模块输出了第一个任务中的注册变量的值,没错,注册变量就是这么简单,使用register关键字指定对应的变量名即可。

上述playbook执行后,可以在控制台中看到名为"[shell module return values]"的任务中已经显示了第一个任务的返回值的信息,返回信息如下:

TASK [shell module return values] **********************************************************************
ok: [test70] => {
"testvar": {
"changed": true,
"cmd": "echo test > /var/testshellfile",
"delta": "0:00:00.003808",
"end": "2020-10-29 20:42:37.675382",
"failed": false,
"rc": 0,
"start": "2020-10-29 20:42:37.671574",
"stderr": "",
"stderr_lines": [],
"stdout": "",
"stdout_lines": []
}
}

 从上述返回信息可以看出,返回值是json格式的,上述返回值中包含一些键值对,比如 "changed": true 或 "cmd": "echo test > /var/testshellfile"等, 如果你只是想要获取到返回值中的某一项特定值,只需要指定键值对中的key即可,假设,我只是想要获取到上述返回信息中cmd的值,则可以使用如下两种语法(前文中已经对如下两种语法进行过示例,此处不再赘述)。

语法一
- name: shell module return values
debug:
msg: "{{testvar.cmd}}"
语法二
- name: shell module return values
debug:
msg: "{{testvar['cmd']}}"

或者
- name: shell model return values
debug:
var: testvar.cmd

 上述示例的返回信息为shell模块的返回值,如果你想要了解返回值中每一项的含义,则可以查看官方手册,我使用的是2.4版本的ansible,所以我可以参考2.4版本的官网文档,找到shell模块的介绍,官网链接如下

​https://docs.ansible.com/ansible/2.4/shell_module.html​

不同的模块,返回值也不尽相同,ansible官网对一些常见的返回值进行了总结,链接如下

​https://docs.ansible.com/ansible/2.4/common_return_values.html​

如果你想要查看模块对应的返回值,可以先查找官方手册,但是,并不是所有模块的官方手册中都对模块的返回值进行了描述,你可以使用上述示例中的方法,自己查看模块的返回值,这些返回值不仅仅能够用于输出,通常我们会利用到这些返回值,比如,通过模块的返回值决定之后的一些动作,所以,注册变量在playbook中还是会被经常用到的,在之后的文章中我们会给出示例,此处不用纠结。

 

通过命令行传入变量


除了之前总结过的定义变量的方法,我们还能够在执行playbook时直接传入需要使用的变量,我们来看一小示例,如下:

---
- hosts: test70
remote_user: root
tasks:
- name: "Passing Variables On The Command Line"
debug:
msg: "{{pass_var}}"

 上例中的playbook中,并没有定义pass_var变量,而是直接引用了pass_var变量,我们可以在调用上述playbook时直接从命令行传入pass_var变量,方法如下 :

ansible-playbook cmdvar.yml --extra-vars 'pass_var="cmdline pass var"'

如上例所示,在调用playbook时使用 "--extra-vars" 选项可以传递对应的变量与变量值, "--extra-vars" 是长选项,对应的短选项是"-e",我们也可以一次性传入多个变量,变量之间用空格隔开,如下:

ansible-playbook cmdvar.yml -e 'pass_var="test" pass_var1="test1"'

上例中的playbook中并没有定义pass_var变量,如果在调用playbook时也没有传入pass_var变量,则会报错,其实,我们也可以先在playbook中定义好变量,然后在执行playbook时,再次传入相同名称的变量,最终还是以传入的变量值为准,示例如下:

---
- hosts: test70
remote_user: root
vars:
pass_var: test_default
tasks:
- name: "Passing Variables On The Command Line"
debug:
msg: "{{pass_var}}"

上例的playbook中定义了pass_var变量,其值为"test_default",在执行上述playbook时,从命令行再次传入pass_var变量,命令如下:

ansible-playbook cmdvar.yml -e 'pass_var="test"'

执行上述命令后,你会发现,最终输出的值为"test"而非"test_default",也就是说,命令行传入的变量的优先级要高于playbook中的变量,通过这种方法,我们就能够更加灵活的指定变量的值了。

不仅ansible-playbook命令可以使用"-e"传递变量,ansible命令也同样可以,所以在执行ad-hoc命令时也可以使用同样的方法传入变量,如下:

ansible test70 -e "testvar=test" -m shell -a "echo {{testvar}}"

上述的几个示例从命令行中传递变量时,都是使用了"key=value"的形式,除了使用"key=value"的方式传递变量,ansible还支持通过json的格式传入变量,示例如下:

通过json格式传入两个变量

ansible-playbook cmdvar.yml -e '{"testvar":"test","testvar1":"test1"}'

通过json格式传入稍微复杂一点的变量

ansible-playbook cmdvar.yml -e '{"countlist":["one","two","three","four"]}'

在剧本中引用上述命令传入的countlist变量时,如果想要获取到值"one",则可以使用如下两种语法引用变量

{{countlist[0]}} 或者 {{countlist.0}}

命令行不仅能够传入变量,还能传入变量文件,变量文件中的变量都会一并被传入,变量文件可以是json格式的,也可以是YAML格式的,此处使用YAML格式的变量文件进行示例,示例文件内容如下

# cat /testdir/ansible/testvar
testvar: testvarinfile
countlist:
- one
- two
- three
- four

测试用playbook内容如下

---
- hosts: test70
remote_user: root
tasks:
- name: "Passing Variables On The Command Line"
debug:
msg: "{{testvar}} {{countlist[0]}}"

如playbook所示,playbook中引用了变量文件中定义的两个变量,那么,我们怎样从命令行中将变量文件中的变量传入playbook呢?示例如下

ansible-playbook cmdvar.yml -e "@/testdir/ansible/testvar"

如上述命令所示,使用"@"符号加上变量文件的路径,即可在命令行中传入对应的变量文件,变量文件中的所有变量都可以在playbook中引用,还是很方便的吧。