变量名仅能由字母、数字和下划线组成,且只能以字母开头。
引用变量的一般方法是 {{ 变量名 }},如果出现位置是第1个元素,需要用双引号括起来。
变量可以在如下几个位置定义:
- 在 ansible-playbook 命令行中定义(优先级最高)
- 在资产清单文件中定义(红帽不推荐)
- 在 playbook 通过 vars 定义
- 在 playbook 通过 vars_files 定义
- 通过 host_vars 和 group_vars 目录来定义(红帽推荐)
命令行定义变量
比如,这儿写了一个 playbook,里面引用了未知来源的变量:
# cat demo.yml
---
- hosts: web
remote_user: root
tasks:
- name: stop {{ srv1 }}
service: name="{{ srv1 }}" state=stopped
# ansible-playbook -e 'pname=httpd' demo.yml
如果要指定多个变量值,在单引号里用空格隔开。
在资产清单文件中定义
普通变量:主机组中主机单独定义,优先级高于公共变量
公共变量/组变量:针对主机组中所有主机定义统一变量
资产清单文件如下:
# cat hosts
[allhosts]
servera.lab.example.com shortname=servera
172.25.250.11 shortname=serverb
[allhosts:vars]
domain=lab.example.com
shortname=demo
[web]
servera.lab.example.com
[db]
172.25.250.11
playbook 如下:
# cat hello.yml
---
- hosts: allhosts
tasks:
- name: configure hostname
hostname:
name: "{{ shortname }}.{{ domain }}"
在 playbook 通过 vars 定义
---
- hosts: web
vars:
- shotname: servera
- domain: lab.example.com
tasks:
- name: configure hostname
hostname:
name: "{{ shortname }}.{{ domain }}"
在 playbook 通过 vars_files 定义
playbook如下:
# cat demo.yml
---
- hosts: web
vars_files:
- vars.yml
tasks:
- name: configure hostname
hostname:
name: "{{ shortname }}.{{ domain }}"
变量文件内容如下:
# cat vars.yml
shotname: servera
domain: lab.example.com
通过 host_vars 和 group_vars 目录来定义
在资产清单文件所在的目录中新建两个文件夹 host_vars 和 group_vars。
然后在相应的目录下面,以组名或者主机名创建文件,文件里书写变量。
playbook直接调用变量即可。
变量文件示例如下:
# cat group_vars/web
shotname: servera
domain: lab.example.com
playbook 如下:
# cat demo.yml
---
- hosts: web
tasks:
- name: configure hostname
hostname:
name: "{{ shortname }}.{{ domain }}"
使用 debug 打印变量的值
使用 debug 模块可以将变量的值输出出来(以进行排错)。
一般有两种写法(不能同时混用):
debug:
var: variable-name <== var 选项,直接写变量名
debug:
msg: "{{ variable-name }}" <== msg 选项,变量名要用花括号括起来
示例如下:
# cat demo.yml
---
- hosts: web
vars:
shortname: servera
domain: lab.example.com
tasks:
#- name: print the value of shortname and domain
# debug:
# msg: "{{ shortname }}.{{ domain }}"
- name: print the value of shortname
debug:
var: shortname
- name: print the value of domain
debug:
var: domain
使用 register 捕获命令的输出
在 ansible 中,任何一个模块都会返回 json 格式的数据,即使是错误信息都是 json 格式的。其内每一项都可以通过变量来引用它,引用的前提是先将其注册为变量。我们可以使用 register 来捕获 task 的输出到一个临时的变量。然后根据变量内容进行打印或者处理。
打印注册变量:
# cat demo.yml
---
- name: install httpd and print the result
hosts: web
tasks:
- name: install httpd
yum:
name: httpd
state: installed
register: cy_result
- name: print the value of var
debug:
msg: "{{ cy_result }}"
还可以只取输出结果中的一部分内容。花括号{}表示是一个字典,中括号[]表示是一个数组。
字典值可以使用 "cy_result['results']" 或者 "cy_result.results" 来取,数组值需要使用数字下标 install_result.results[0]来取(注意本例只有一个数组元素)。
处理注册变量:
该例子仅作为练习使用,会有提高和收获,但无实际意义。
要求根据 yum 模块来判断软件是否安装,如果未安装,才调用 yum 模块进行安装。
# cat register.yml
---
- name: check package and and install
hosts: web
tasks:
- name: check httpd if installed
yum:
list: httpd
register: check_result
- name: install httpd if not installed
yum:
name: httpd
state: installed
when: check_result['results'][0]['yumstate'] == 'available'
- name: use debug module to print the temporary variable
debug: var=check_result['results'][0]['yumstate']
using arrays as variables
考虑如下经常遇到的场景:
user1_first_name: san
user1_last_name: zhang
user1_home_dir: /home/zhangsan
user2_first_name: si
user2_last_name: li
user2_home_dir: /home/lisi
对于类似的需求,我们可以使用 arrays 来完成:
---
- name: using arrays as variables
hosts: web
vars:
users:
zhangsan:
first_name: san
last_name: zhang
lisi:
first_name: si
last_name: li
tasks:
- name: print the value of var
debug:
#msg: "{{ users.zhangsan.first_name }}"
msg: "{{ users['zhangsan']['first_name'] }}"
注意: 当使用 . 这种书写方式时,如果 key 的名字跟 python 的 method/attributes 一样,例如 discard, copy, add 等,则会报错,使用 [] 可以避免这种问题。