[TOC]
0x04 variable变量 前言:在ansible中使用变量,能让我们的工作变得更加灵活,在ansible中变量的使用方式有很多种
ansible变量规则:
变量名应该由字母、数字、下划线组成
变量名需要以字母开头
ansible内置的关键字不能作为变量名
下面是优先级从最小到最大的顺序(最后列出的变量赢得优先级):
command line values (eg “-u user”)
role defaults [1]
inventory file or script group vars [2]
inventory group_vars/all [3]
playbook group_vars/all [3]
inventory group_vars/* [3]
playbook group_vars/* [3]
inventory file or script host vars [2]
inventory host_vars/* [3]
playbook host_vars/* [3]
host facts / cached set_facts [4]
play vars
play vars_prompt
play vars_files
role vars (defined in role/vars/main.yml)
block vars (only for tasks in block)
task vars (only for the task)
include_vars
set_facts / registered vars
role (and include_role) params
include params
extra vars (always win precedence)
(1) vars 配置定义 (playbook) 在play中定义变量的几种形式:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 vars: tvar1: testfile tvar2: testfile vars: - testvar1: testfile1 - testvar2: testfile2 vars: nginx: conf80: /etc/nginx/conf.d/80.conf conf8080: /etc/nginx/conf.d/8080.conf
变量引用的几种方式:1 2 3 4 5 6 7 8 "{{ tvar1 }}" "{{ testvar1 }}" "{{nginx.conf80}}" "{{nginx['conf8080']}}"
上例中我在引用变量时使用了双引号,而在本文的第一个示例中引用变量时却没有使用双引号,这是因为第一个示例中的变量在被引用时,并没有处于”开头的位\”,第一个示例中变量被引用时如下:1 2 3 path: /testdir/{{ testvar1 }} path: "{{nginx.conf80}}"
上述情况也有例外,当在playbook中为模块的参数赋值时,可以使用”冒号”,也可以使用”等号”,当使用”等号”为模块的参数赋值时,则不用考虑引用变量时是否使用”引号”的问题,1 2 3 file: path={{nginx.conf80}} path={{nginx['conf8080' ]}}
(2) vars_files 独立yml文件定义 在某些场景中我们还可以在某个文件中定义变量,然后再在playbook中引入对应的文件,引入文件后playbook即可使用文件中定义的变量,即可使用文件中定义的变量
你可能会问为什么要多此一举呢?
某些工作场景中需要你想要让别人阅读你的playbook,却不想让别人看到某些值只能看到引入的变量名,但是看不到变量对应的值,这种将变量分离到某个文件中的做法叫做”变量文件分离”
“变量文件分离”:能够隐藏某些值,将不同类的信息放在不同的文件,变量信息与剧本分离(方便修改)
“变量文件分离”之变量定义 建立nginx.yml在文件中定义变量时,不要使用vars关键字,直接定义变量即可,定义变量的语法与在playbook中定义变量的几种语法相同1 2 3 4 5 6 7 8 9 10 testvar1: testfile testvar2: testfile2 - testvar1: testfile - testvar2: testfile2 nginx: conf80: /etc/nginx/conf.d/80.conf conf8080: /etc/nginx/conf.d/8080.conf
“变量文件分离”之变量包含引用 1 2 3 4 5 6 7 8 9 10 11 12 13 14 vars_files: - /testdir/ansible/nginx.yml vars_files: - /testdir/ansible/nginx_vars.yml - /testdir/ansible/other_vars.yml vars: - conf90: /etc/nginx/conf.d/90.conf vars_files: - /testdir/ansible/nginx_vars.yml
基础示例:实现变量文件分离引用与命令模块文件模块使用1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 create: directory: Love filename: Ansible.sh context: "insert file a talk about \b \t \n" --- - hosts: local remote_user: root vars: - dirRoot: /tmp/ vars_files: - /root/var.yml tasks: - name: Create directory file: path: "{{dirRoot}} {{create.directory}} " state: directory - name: touch file file: path={{dirRoot}}{{create.directory}}/{{create['filename']}} state=touch - name: insert context lineinfile: path="{{dirRoot}}{{create.directory}}/{{create.filename}}" line={{create['context']}}
weiyigeek.top-变量分离案例
(3) 变量相关使用方法 描述:这篇文章所涉及到的内容需要借助两个模块,所以在详细的总结变量的相关使用方法之前会先描述一下这两个模块的用法:setup模块/debug模块
。
当我们运行一个playbook时自动调用了setup模块从而执行了"[Gathering Facts]"任务
,通过这个默认任务收集远程主机的相关信息(例如远程主机的IP地址,主机名,系统版本,硬件配置等信息
); 其实这些被收集到的远程主机信息会保存在对应的变量中,当我们要使用这些信息时就可以获取对应的变量;
其实这些远程主机的变量信息不仅仅能够用于输出,我们通常会获取到信息以后对这些信息的值进行判断
,判断是否符合我们的要求然后再执行下一步动作,比如先获取到远程主机的系统发行版信息然后判断发行版是centos6还是centos7:
如果是centos6,我们就将准备好的A文件拷贝到远程主机中
如果是centos7,我们就将准备好的B文件拷贝到远程主机中
演示案例:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 $ansible local -m setup | morelocal | SUCCESS => { "ansible_facts" : { "ansible_all_ipv4_addresses" : [ "10.10.107.222" , "192.168.1.99" ], "ansible_all_ipv6_addresses" : [ "fe80::9738:2d26:820f:2d50" , "fe80::dfc:592e:b4a4:9877" ], "ansible_apparmor" : { "status" : "disabled" }, "ansible_architecture" : "x86_64" , "ansible_bios_date" : "09/21/2015" , "ansible_bios_version" : "6.00" , "ansible_cmdline" : { "BOOT_IMAGE" : "/vmlinuz-3.10.0-957.12.2.el7.x86_64" , "LANG" : "zh_CN.UTF-8" , "crashkernel" : "auto" , "quiet" : true , "rd.lvm.lv" : "centos/swap" , "rhgb" : true , "ro" : true , "root" : "/dev/mapper/centos-root" },
执行上述命令后远程主机local的相关信息将会输出到ansible主机的控制台上,为了方便你阅读返回的信息的格式是json格式
ansible已经将格式化后的json信息返回到了控制台中比如:
“ansible_all_ipv4_addresses” 表示远程主机中的所有ipv4地址,从其对应的值可以看出,local主机上一共有3个ipv4地址。
“ansible_distribution” 表示远程主机的系统发行版,从其对应的值可以看出local主机的系统发行版为centos
“ansible_distribution_version” 表示远程主机的系统版本号,从其对应的值与 “ansible_distribution” 的值可以看出local主机的系统版本为centos7.4
“ansible_ens35” 表示远程主机ens35网卡的相关信息,细心如你一定也发现了,我还有两个名为”ens33”和”ens34”的网卡,只不过为了方便示例,这两个网卡的信息被我省略了。
“ansible_memory_mb” 表示远程主机的内存配置信息。
我们还可以通过关键字对信息进行过滤还能使用通配符进行相对模糊的过滤:1 2 3 4 5 ansible local -m setup -a 'filter=ansible_memory_mb' ansible local -m setup -a "filter=*mb*"
weiyigeek.top-set模块
其实除了这些信息以外还能够在远程主机中写入一些自定义的信息,这些自定义信息也可以被setup模块收集到。那么我们应该在哪里定义这些信息呢?该怎样定义这些信息呢? 答:ansible 默认会去目标主机的 /etc/ansible/facts.d 目录下查找主机中的自定义信息,并且规定自定义信息需要写在以\”.fact\”为后缀的文件中,同时这些以”.fact”为后缀的文件中的内容需要是INI格式或者是json格式的
。
当setup收集远程主机的”local facts”时,默认会查找远程主机的/etc/ansible/facts.d
目录,如果你把"local facts"信息文件放在了其他自定义路径
,在使用setup模块时,需要使用”fact_path”参数指定对应的路径;
那么我们来创建一个测试文件路径为local主机的 /etc/ansible/facts.d/testinfo.fact
在文件中写入如下INI格式的信息。1 2 3 4 5 6 7 8 9 10 11 12 13 14 $cat testinfo.fact[testmsg] msg1 = This is a demo1 msg2 = This is a demo2 { "testmsg" :{ "msg1" :"This is the first custom test message" , "msg2" :"This is the second custom test message" } }
通过上述方式在目标主机的本地自定义信息被称为”local facts”,当我们运行setup模块时,远程主机的"local facts"信息也会被收集
,我们可以通过”ansible_local”关键字过滤远程主机的”local facts”信息
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 ansible local -m setup -a "filter=ansible_local" ansible local -m setup -a "filter=ansible_local fact_path=/tmp" local | SUCCESS => { "ansible_facts" : { "ansible_local" : { "testinfo" : { "testmsg" : { "msg1" : "This is a demo1" , "msg2" : "This is a demo2" } } }, "discovered_interpreter_python" : "/usr/bin/python" }, "changed" : false } local | SUCCESS => { "ansible_facts" : { "ansible_local" : { "info" : { "testmsg" : { "msg1" : "This is the first custom test message" , "msg2" : "This is the second custom test message" } } }, "discovered_interpreter_python" : "/usr/bin/python" }, "changed" : false }
除了上面的setup模块我们还能采用,debug模块的作用就是帮助我们进行调试并且把信息输出到ansible控制台上,以便我们能够定位问题;debug模块除了能够使用msg参数输出自定义的信息,还能够通过debug模块直接输出变量信息需要使用var参数
那么我们先来看一个debug模块的playbook小示例如下:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 --- - hosts: local remote_user: root vars: testvar: value of test variable 1024 tasks: - name: touch testfile file: path: /tmp/testfile state: touch - name: debug demo debug: msg: "this is debug info , {{testvar}} " ``` play解析:我们先在local主机上touch了对应的文件,使用debug的msg参数时也可以引用变量的值并且输出,然后利用debug模块在控制台中输出变量的名称以及变量的值: ```bash TASK [debug demo] ok: [local] => { "msg": "this is debug info , value of test variable 1024 " } TASK [debug demo] ok: [local] => { "testvar": "value of test variable 1024" }
playbook在运行时默认运行”[Gathering Facts]”任务会收集远程主机的相关信息,这些信息会保存在对应的变量中,我们在playbook中可以使用这些变量,从而利用这些信息,那么我们怎样在playbook获取到这些变量的值呢?
在setup模块的示例中我们可以通过"ansible_memory_mb"
关键字获取远程主机的内存信息,其实在playbook中也可以直接调用”ansible_memory_mb”变量名;1 2 3 4 5 6 7 8 9 --- - hosts: local remote_user: root vars: test: "Test: " tasks: - name: debug demo debug: msg: "{{test}} Remote host memory swap information: {{ansible_memory_mb['swap']}} \n, ip addrs info: {{ansible_all_ipv4_addresses}} "
我们自定义的信息中包含了变量内容,远程主机的内存信息/IP地址信息同时被输出了,执行结果:1 2 3 4 TASK [debug demo] ok: [local ] => { "msg" : "Test: Remote host memory swap information: {u'cached': 0, u'total': 2047, u'free': 2047, u'used': 0} \n, ip addrs info: [u'10.10.107.222', u'192.168.1.99']" }
如上述返回信息所示,”ansible_memory_mb”中其实包含了"nocache"、"real"、 "swap"
三个部分的信息,如果我们只想获得\”real\”部分的信息,在playbook中引用变量时可以使用如下两种语法。1 2 3 4 5 6 语法一示例: debug: msg: "Remote host memory information : {{ansible_memory_mb.real}}" 语法二示例: debug: msg: "Remote host memory information : {{ansible_memory_mb['real']}}"
总结:
其实setup模块返回的这些信息都存在了对应的变量中,我们可以通过引用变量从而使用对应的信息;
其实debug模块常常用来调试playbook,输出自定义异常以及setup信息收集的变量输出;
(4) register 注册变量 描述:ansible的模块在运行之后其实都会返回一些”返回值”,只是默认情况下这些”返回值”并不会显示而已,我们可以把这些返回值写入到某个变量中,然后通过引用对应的变量从而获取到这些返回值,这种将模块的返回值写入到变量中的方法被称为"注册变量"
;
这些返回值不仅仅能够用于输出通常我们会利用到这些返回值,比如通过模块的返回值决定之后的一些动作,所以注册变量在playbook中还是会被经常用到的;
基础示例:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 --- - hosts: local remote_user: root vars: cmd1: whoami cmd2: hostname -I tasks: - name: execute whoami shell: "{{cmd1}} " register: who - name: execute hostname shell: "{{cmd2}} " register: hostname - name: execute echo shell: "echo test > /tmp/testshellfile" register: echovar - name: Debug shell module return values debug: var: who,hostname,echovar
执行结果:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 TASK [Debug shell module return values] ok: [local] => { "who,hostname,echovar" : "( {'stderr_lines': [], u'changed': True, #操作标识! u'end': u'2019-07-30 11:31:13.821710', 'failed': False, #执行状态 u'stdout': u'root', #执行结果 u'cmd': u'whoami', #执行命令 u'rc': 0, u'start': u'2019-07-30 11:31:13.818264', u'stderr': u'', u'delta': u'0:00:00.003446', 'stdout_lines': [u'root']}, {'stderr_lines': [], u'changed': True, u'end': u'2019-07-30 11:31:14.111808', 'failed': False, u'stdout': u'10.10.107.222 192.168.1.99 ', u'cmd': u'hostname -I', u'rc': 0, u'start': u'2019-07-30 11:31:14.108345', u'stderr': u'', u'delta': u'0:00:00.003463', 'stdout_lines': [u'10.10.107.222 192.168.1.99 ']}, {'stderr_lines': [], u'changed': True, u'end': u'2019-07-30 11:31:14.367277', 'failed': False, u'stdout': u'', u'cmd': u'echo test > /tmp/testshellfile', u'rc': 0, u'start': u'2019-07-30 11:31:14.364389', u'stderr': u'', u'delta': u'0:00:00.002888', 'stdout_lines': []})" }
假设我只是想要获取到上述返回信息中cmd的值则可以使用如下两种语法:1 2 3 4 5 6 7 8 9 10 11 - name: shell module return values debug: msg: "{{testvar.cmd}}" - name: shell module return values debug: msg: "{{testvar['cmd']}}"
参考来源:
(5) prompt 提示输入写入变量 描述:在某些交换式操作的时候,脚本会提示用户输入一些信息,脚本需要根据用户输入的信息决定下一步的动作
那么在playbook中该怎样实现这种交互呢? 答:我们可以这样做提示用户输入信息,然后将用户输入的信息存入到指定的变量中,当我们需要使用这些”输入的信息”时,只要引用对应的变量即可。
示例解析:使用"vars_prompt"
关键字创建了两个变量,两个变量的名称分别为”your_name” 和 “your_age”,当用户输入后字符串将被存入变量之中;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 --- - hosts: local remote_user: root vars_prompt: - name: "Username" prompt: "What is your name" private: no - name: "Password" prompt: "What is your password" - name: "Sex" prompt: "Choose the you Sex \n m: Man\n w: Woman\n o: other\n" private: no default: o - name: "PayPass" prompt: "Enter Pay PassWord" private: no unsafe: yes encrypt: "sha512_crypt" confirm: yes tasks: - name: output prompt vars debug: msg: "Username = {{Username}} , Password = {{Password}} , Sex = {{Sex}} , Pay Password = {{PayPass}} " - name: create user user: name: "{{Username}} " password: "{{PayPass}} " bcrypt - BCrypt md5_crypt - MD5 Crypt sha256_crypt - SHA-256 Crypt sha512_crypt - SHA-512 Crypt
执行结果:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 $ansible-playbook prompt.yml What is your name: Weiyegeek What is your password: Choose the you Sex: m: Man w: Woman o: other [o]: m Enter Pay PassWord: Wei123456 confirm Enter Pay PassWord: Wei123456 PLAY [local] TASK [Gathering Facts] ok: [local] TASK [output prompt vars] ok: [local] => { "msg": "Username = Weiyegeek , Password = weiyegeek, Sex = m, Pay Password = $6$WDmSQbaDomZyzbbm$MHXVXALnaZ4oKkptiFi/CYlQJWxrUD4xxHmvSjvZSKqr/4hvmaA/h/JKLIUZL.YZDQXx53EAOp.BgJLPltnxw1" } TASK [create user] changed: [local] PLAY RECAP local : ok=3 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
weiyigeek.top-prompt-createuser
注意事项:
当使用”encrypt”关键字对字符串进行哈希时,ansible需要依赖Python的passlib库完成哈希操作,1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 python -m pip install passlib des_crypt - DES Crypt bsdi_crypt - BSDi Crypt bigcrypt - BigCrypt crypt16 - Crypt16 md5_crypt - MD5 Crypt bcrypt - BCrypt sha1_crypt - SHA-1 Crypt sun_md5_crypt - Sun MD5 Crypt sha256_crypt - SHA-256 Crypt sha512_crypt - SHA-512 Crypt apr_md5_crypt - Apache’s MD5-Crypt variant phpass - PHPass’ Portable Hash pbkdf2_digest - Generic PBKDF2 Hashes cta_pbkdf2_sha1 - Cryptacular’s PBKDF2 hash dlitz_pbkdf2_sha1 - Dwayne Litzenberger’s PBKDF2 hash scram - SCRAM Hash bsd_nthash - FreeBSD’s MCF-compatible nthash encoding
官方文档[prompt]:https://docs.ansible.com/ansible/latest/user_guide/playbooks_prompts.html
描述:除了上面定义变量的方法,我们还能够在执行playbook时直接传入需要使用的变量;
比如下面再playbook中并没有定义变量但我们可以在调用playbook时直接从命令行传入变量,果在调用playbook时也没有传入变量则会报错,其实我们也可以先在playbook中定义好变量,然后在执行playbook时以传入变量覆盖playbook中的变量值(前提是命令行中的变量与play中的变量重名):1 2 3 4 5 6 7 8 9 10 --- - hosts: local remote_user: root vars: verify: "123456" tasks: - name: "Passing Variables On The Command Line" debug: msg: "{{ip}} - {{Port}} - {{service}} , Verify: {{verify}} "
执行结果:1 2 3 4 5 6 7 8 9 ansible-playbook extravars.yml --extra-vars 'ip="192.168.1.1" Port="8080" service="nginx" verify="888888"' ansible-playbook extravars.yml -e 'ip="192.168.1.1" Port="8080" service="nginx" verify="888888"' ansible-playbook extravars.yml -e '{"ip":"192.168.1.1","Port":"8080","service":"nginx","verify":"888888"}' ok: [local ] => { "msg" : "192.168.1.1 - 8080 - nginx , Verify: 888888" }
命令行传入变量文件 描述:命令行不仅能够传入变量还能传入变量文件
,变量文件中的变量都会一并被传入,变量文件可以是json格式的/YAML格式的,此处使用YAML格式的变量文件进行示例1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 testvar: testvarinfile countlist: - one - two - three - four end --- - hosts: local remote_user: root tasks: - name: "Passing Variables On The Command Line" debug: msg: "{{testvar}} {{countlist[0]}} " END
那么我们怎样从命令行中将变量文件中的变量传入playbook呢? 1 2 3 4 5 6 7 8 ansible-playbook filevariable.yml -e "@/root/filevars.yml" TASK [Passing Variables On The Command Line] ok: [local ] => { "msg" : "testvarinfile one" }
总结:
命令行传入的变量的优先级要高于playbook中的变量,通过这种方法我们就能够更加灵活的指定变量的值了。
命令行传入json字符串来设置变量1 2 3 ansible-playbook cmdvar.yml -e '{"testvar":"test","testvar1":"test1"}' ansible-playbook cmdvar.yml -e '{"countlist":["one","two","three","four"]}'
命令行可以传入单个或者多个变量也能传入变量文本文件采用-e选项直接搞定;
(7) 变量使用方法 set_fact 描述:在清单中配置变量,我们知道可以在清单中配置需要被管理的远程主机,也可以将部分远程主机分为一组,其实在配置清单时还可以为主机或主机组设置变量
;
主机变量 在清单中配置远程主机时,可以同时为主机配置对应的变量,当操作这个主机时即可直接使用对应的变量。1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 local ansible_host=10.1.1.70 testhostvar=test70_host_var testvar1=testvar1all: hosts: test70: ansible_host: 10.1.1.70 ansible_port: 22 testhostvar: test70_host_var testhostvar1: test70_host_var1 testhostvar2: thv1: demo1 thv2: demo2
执行结果:1 2 3 4 ansible local -m shell -a "echo -e Testhostvar = {{testhostvar}}, \n Testhostvar1 = {{testhostvar1}} , testhostvar2.thv1 = {{testhostvar2['thv2']}}"
注意: 主机变量的生效范围只限于对应的主机
主机组变量 在清单中我们能将多个主机分为一组方便我们成批的操作远程主机,同样我也可以将变量配置是到组里面;使用vars关键字可以指定组变量,vars关键字位于对应组的下一级1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 [testB] test70 ansible_host=10.1.1.70 test71 anisble_host=10.1.1.71 [testB:vars] test_group_var1='group var test' test_group_var2='group var test2' all: children: testB: hosts: test70: ansible_host: 10.1.1.70 ansible_port: 22 test71: ansible_host: 10.1.1.71 ansible_port: 22 vars: test_group_var1: 'group var test1' test_group_var2: 'group var test2'
执行结果:1 2 3 $ansible ops -m shell -a "echo -e test_group_var1= {{test_group_var1}}, \n test_group_var2 = {{test_group_var2}}"
set_fact定义变量 描述:set_fact是一个模块,我们可以通过set_fact模块在tasks中定义变量,并且与register的功能很相似,也是将值赋值给变量。它更像shell中变量的赋值方式,可以将某个变量的值赋值给另一个变量,也可以将字符串赋值给变量。
其实通过set_fact模块创建的变量还有一个特殊性,通过set_fact创建的变量就像主机上的facts信息一样可以在之后的play中被引用
,而直接在play中采用vars设置变量只能在当前主机
基础示例:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 --- - hosts: local remote_user: root vars: testvar1: tv1 tasks: - name: "test shell return variable" shell: "echo setfact module" register: revar - name: setfact moudle setting set_fact: testvar2: tv2 testvar3: "{{revar.cmd}} " cacheable: yes - debug: msg: "Local host : {{testvar1}} - {{testvar2}} - {{testvar3}} - {{revar.cmd}} " - hosts: local remote_user: root tasks: - name: "other play get testvar2" debug: msg: "{{testvar2}} " - name: "other play get testvar3" debug: msg: "{{testvar3}} " - name: "show execute command" debug: msg: "{{revar.cmd}} " end
执行结果:1 2 3 4 5 6 7 8 9 10 11 12 $ansible -playbook setfact.yml
总结:
(8) 内置变量 ansible中还有一些内置变量可供我们使用,内置变量的变量名是被ansible保留的,当我们定义变量时不能使用这些变量名。
内置变量一览表:
1.ansible_version : 获取到ansible的版本号
2.inventory_dir : 获取到ansible主机中清单文件的存放路径,ansible默认的清单文件/etc/ansible/hosts
3.inventory_hostname: 获取到被操作的当前主机的主机名称(对应主机在清单中配置的名称)
4.inventory_hostname_short : 与内置变量inventory_hostname类似但是这个名称更加简短;
5.groups : 获取到清单中”所有分组”的”分组信息”
6.group_names : 获取到当前主机所在分组的组名
7.hostvars : 帮助我们在操作当前主机时获取到其他主机中的信息
8.play_hosts : 获取到当前play所操作的所有主机的主机名列表
内置变量使用案例:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 ansible local -m debug -a "msg='当前Ansible版本号: {{ansible_version}}'" ansible local -m debug -a "msg='Current Hosts Configure: {{inventory_dir}}'" $ansible local -m debug -a "msg={{inventory_hostname}}" $ansible testA -m debug -a "msg={{inventory_hostname}}" $ansible testA -m debug -a "msg={{inventory_hostname_short}}" ansible local -m debug -a "msg={{groups}}" ansible local -m debug -a "msg={{groups.testA}}" ansible ops -m debug -a "msg={{groups['ungrouped']}}" ansible local -m debug -a "msg={{group_names}}" ansible testA -m debug -a "msg={{group_names}}"
重点介绍:hostvars 变量内置 描述:通过”set_fact”结合”hostvars”的方式,实现了跨play获取其他主机中的变量信息的功能还是很方便的,并且通过gather_facts关键字来控制当前play是否收集对应主机的facts信息[yes|no]
实际案例1:hostvars 与 play_hosts内置变量联合使用1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 --- - name: "Play1 : Gather facts of local" hosts: local,testB remote_user: root tasks: - name: "show play hosts" debug: msg: "Play1 -> play include hosts : {{play_hosts}} " - name: "Play2: Gather facts" hosts: testA,testB remote_user: root tasks: - debug: msg: "Play2 -> Local IP : {{hostvars['local'].ansible_default_ipv4}} " - debug: msg: "Play2 -> Local interface : {{hostvars['local'].ansible_default_ipv4.interface}} " end
执行结果:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 TASK [Gathering Facts] ok: [10.20.172.179] ok: [local ] ok: [local ] "msg" : "Play1 -> play include hosts : [u'local', u'10.20.172.179']" ok: [10.20.172.179] "msg" : "Play1 -> play include hosts : [u'local', u'10.20.172.179']" TASK [Gathering Facts] ok: [10.20.172.179] ok: [10.10.107.221] ok: [10.10.107.221] => { "msg" : "Play2 -> Local IP : {u'macaddress': u'00:50:56:b3:dc:b4', u'network': u'10.10.107.0', u'mtu': 1500, u'broadcast': u'10.10.107.255', u'alias': u'ens192', u'netmask': u'255.255.255.0', u'address': u'10.10.107.222', u'interface': u'ens192', u'type': u'ether', u'gateway': u'10.10.107.1'}" } ..... ok: [10.20.172.179] => { "msg" : "Play2 -> Local interface : ens192" } ......
使用”gather_facts”关键字可以控制play是否进行Gathering Facts主机的信息收集;
第一个play中的”gather_facts: no”表示设置当前play不收集对应主机的信息,无法获取到local主机中的facts信息,原因是local的facts信息并未被收集过,所以调用其他主机的facts信息的前提是对应主机的facts信息已经被收集过。
其实除了facts信息,我们还能够利用hostvars内置变量从别的主机中获取到其他类型的一些变量信息,比如其他主机的注册变量、主机变量、组变量等信息,还有就是注册变量并不用像facts信息那样需要事先收集
,即可直接通过hostvars跨主机被引用到;
实际案例2:hostvars 与 gather_fcats 与 set_fact模块案例:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 --- - name: "Play 1 - local" hosts: local remote_user: root gather_facts: no vars: testvar: "通过vars关键字定义的变量方法是无法被跨主机引用的" tasks: - name: "setfact module settting" set_fact: var1: "gather_facts settting no" - name: "show set_fact" shell: "echo {{var1}} " register: shellrst - name: "Play 2 - testA " hosts: testA remote_user: root gather_facts: no tasks: - debug: msg: "Play 1 hostvars : {{hostvars.local.var1}} , Play 1 register shell command: {{hostvars.local.shellrst['cmd']}} " end
执行结果:1 2 3 4 TASK [debug] ok: [10.10.107.221] => { "msg" : "Play 1 hostvars : gather_facts settting no , Play 1 register shell command: echo gather_facts settting no" }
(9) include_vars 更新变量文件 描述:前面我们学习了var_files也知道了它的应用场景,但是使用var_files有一个缺点,就是当变量文件动态的被添加变量的时候,其后的playbook并不能读取变化增加的变量值;
但是我们可以依靠include_vars模块
能够在任务执行过程中,随时的引入变量文件,以便动态的获取到最新的变量文件内容;1 2 3 4 - include_vars: file: /testdir/ansible/testfile - include_vars: "/testdir/ansible/testfile"
基础示例:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 --- - hosts: local remote_user: root gather_facts: no vars_files: - /tmp/ansible/demo1/var.yml tasks: - debug: msg: "{{test1}} {{test2}} " - lineinfile: path: /tmp/ansible/demo1/var.yml line: "testvar4: add" - include_vars: file: /tmp/ansible/demo1/var.yml name: trans_var - debug: msg: "include_vars - {{trans_var.testvar4}} " - include_vars: dir: /tmp/ansible/demo2/ files_matching: "^var.*" ignore_files: ["^var_.*",varintest.yaml] extensions: [yaml,yml,json,varfile] depth: 1 name: var register: returnval - debug: msg: "{{var}} -> {{returnval.ansible_included_var_files}} " END
执行结果:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 ok: [local ] => {"msg" : "qixi happy" } changed: [local ] ok: [local ] ok: [local ] => {"msg" : "include_vars - add" } ok: [local ] ok: [local ] => { "msg" : "{u'test3': u'include_varDemo', u'test4': u'WeiyiGeek'} -> [u'/tmp/ansible/demo2/var.yml']" } local : ok=6 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0