黑帽联盟

 找回密码
 会员注册
查看: 892|回复: 0
打印 上一主题 下一主题

[基础服务] ansible笔记(17):变量(四)

[复制链接]
yun 黑帽联盟官方人员 

920

主题

37

听众

1364

积分

超级版主

Rank: 8Rank: 8

  • TA的每日心情
    奋斗
    2019-10-18 11:20
  • 签到天数: 678 天

    [LV.9]以坛为家II

    本帖最后由 yun 于 2019-9-11 17:22 编辑

    ansible是一个系列文章,我们会尽量以通俗易懂的方式总结ansible的相关知识点。
    ansible系列博文直达链接:ansible轻松入门系列
    "ansible系列"中的每篇文章都建立在前文的基础之上,所以,请按照顺序阅读这些文章,否则有可能在阅读中遇到障碍。


    这篇文章继续总结一些ansible中使用变量的方法。

    在清单中配置变量
    在ansible系列文章的前几篇文章中,我们总结了ansible清单的配置方法,在清单中,可以配置需要被管理的远程主机,也可以将部分远程主机分为一组,其实,在配置清单时,还可以为主机或主机组设置变量,具体方法见如下总结

    主机变量
    在清单中配置远程主机时,可以同时为主机配置对应的变量,当操作这个主机时,即可直接使用对应的变量。
    比如,我在/etc/ansible/hosts中定义test70主机时,可以为test70主机配置一个名为testhostvar的变量,变量值为test70_host_var,示例如下
    1. test70 ansible_host=10.1.1.70 testhostvar=test70_host_var
    复制代码
    如上例所示,只要在定义主机时将变量名和变量值写在主机配置的后面即可,可以为一个主机定义多个主机变量,用空格隔开即可,很方便吧,那么我们来测试一下,看看在操作test70主机时,能否引用到这个变量,为了方便示例就不编写playbook了,输入如下ad-hoc命令即可测试出效果
    1.png
    如上图所示,操作test70主机时,testhostvar已经被引用到了,当然,testhostvar是test70的主机变量,其他主机并不能引用到这个变量,主机变量的生效范围只限于对应的主机。

    前文中总结过,配置清单时可以使用INI格式或者YAML格式的语法,刚才的示例为INI风格的语法配置,YAML格式的配置中,可以使用如下方法配置变量
    1. all:
    2. hosts:
    3.    test70:
    4.      ansible_host: 10.1.1.70
    5.      ansible_port: 22
    6.      testhostvar: test70_host_var
    7.      testhostvar1: test70_host_var1
    复制代码
    如上例所示,我们为test70主机配置了两个变量,testhostvar和testhostvar1,没错,就是这么简单,直接在test70的下一级写明变量与变量值即可。
    你也可以使用如下方法配置有"层级"的变量,如下
    1. all:
    2. hosts:
    3.    test70:
    4.      ansible_host: 10.1.1.70
    5.      ansible_port: 22
    6.      testhostvar: test70_host_var
    7.      testhostvar1: test70_host_var1
    8.      testhostvar3:
    9.        thv31: 3.1
    10.        thv32: 3.2
    复制代码
    根据前文的总结,聪明如你一定已经想到了,我们可以使用如下两种方法引用变量中的值
    2.png

    主机组变量
    在清单中,我们能将多个主机分为一组,这样方便我们成批的操作远程主机。
    比如,我在清单中将test70与test71分为一组,组名为testB,INI格式的配置如下
    1. [testB]
    2. test70 ansible_host=10.1.1.70
    3. test71 anisble_host=10.1.1.71
    复制代码
    如果我们想为testB组配置组变量,该怎么办呢?示例如下
    1. [testB]
    2. test70 ansible_host=10.1.1.70
    3. test71 anisble_host=10.1.1.71

    4. [testB:vars]
    5. test_group_var1='group var test'
    6. test_group_var2='group var test2'
    复制代码
    如上例所示,"[testB:vars]"表示为testB组配置变量,上例中,testB组中一共定义了两个组变量,"test_group_var1"和"test_group_var2"
    组变量的使用范围为组中的所有主机,上例中,无论test70还是test71,都可以使用到上述两个变量,效果如下。
    3.png

    上例为INI格式中配置组变量的方法,YAML格式中配置组变量的示例如下
    1. all:
    2. children:
    3.    testB:
    4.      hosts:
    5.        test70:
    6.          ansible_host: 10.1.1.70
    7.          ansible_port: 22
    8.        test71:
    9.          ansible_host: 10.1.1.71
    10.          ansible_port: 22
    11.      vars:
    12.        test_group_var1: 'group var test1'
    13.        test_group_var2: 'group var test2'
    复制代码
    如上例所示,使用vars关键字可以指定组变量,vars关键字位于对应组的下一级,上例中,vars关键字位于testB的下一级,调用组变量的效果如下
    4.png

       通过set_fact定义变量
    set_fact是一个模块,我们可以通过set_fact模块在tasks中定义变量,先来看一个小示例,如下
    1. ---
    2. - hosts: test70
    3.   remote_user: root
    4.   tasks:
    5.   - set_fact:
    6.       testvar: "testtest"
    7.   - debug:
    8.       msg: "{{testvar}}"
    复制代码
    如上例所示,我们通过set_fact模块定义了一个名为testvar的变量,变量值为testtest,然后使用debug模块输出了这个变量。
    是不是很简单,通过set_fact模块就能够在tasks中定义变量了,我们也可以通过set_fact将一个变量的值赋予另一个变量,示例如下
    1. ---
    2. - hosts: test70
    3.   remote_user: root
    4.   vars:
    5.     testvar1: test1_string
    6.   tasks:
    7.   - shell: "echo test2_string"
    8.     register: shellreturn
    9.   - set_fact:
    10.       testsf1: "{{testvar1}}"
    11.       testsf2: "{{shellreturn.stdout}}"
    12.   - debug:
    13.       msg: "{{testsf1}} {{testsf2}}"
    复制代码
    上例中,我们先定义了一个变量testvar1,又使用register将shell模块的返回值注册到了变量shellreturn中,
    之后,使用set_fact模块将testvar1变量的值赋予了变量testsf1,将shellreturn变量中的stdout信息赋值给了testsf2变量,
    最后,使用debug模块输出了testsf1与testsf2的值。

    如上述示例所示,set_fact模块可以让我们在tasks中创建变量,也可以将一个变量的值赋值给另一个变量。

    其实,通过set_fact模块创建的变量还有一个特殊性,通过set_fact创建的变量就像主机上的facts信息一样,可以在之后的play中被引用,什么意思呢?我们慢慢聊。
    前文中已经总结过,默认情况下,每个play执行之前都会执行一个名为"[Gathering Facts]"的默认任务,这个任务会收集对应主机的相关信息,我们可以称这些信息为facts信息,我们已经总结过怎样通过变量引用这些facts信息,此处不再赘述,而通过set_fact模块创建的变量可以在之后play中被引用,就好像主机的facts信息可以在play中引用一样,这样说可能还是不是特别容易理解,不如来看一个小例子,如下
    1. ---
    2. - hosts: test70
    3.   remote_user: root
    4.   vars:
    5.     testvar1: tv1
    6.   tasks:
    7.   - set_fact:
    8.       testvar2: tv2
    9.   - debug:
    10.       msg: "{{testvar1}} ----- {{testvar2}}"

    11. - hosts: test70
    12.   remote_user: root
    13.   tasks:
    14.   - name: other play get testvar2
    15.     debug:
    16.       msg: "{{testvar2}}"
    17.   - name: other play get testvar1
    18.     debug:
    19.       msg: "{{testvar1}}"
    复制代码
    上例中一共有两个play,第一个play中,我们通过两种方式创建了两个变量,第一个变量testvar1使用vas关键字创建,第二个变量使用set_fact创建。
    如果执行上例的playbook,可以发现,这两个变量在第一个play中都可以正常的输出。但是在第二个play中,testvar2可以被正常输出了,testvar1却不能被正常输出,会出现未定义testvar1的错误,因为在第一个play中针对test70主机进行操作时,testvar1是通过vars关键字创建的,而testvar2是通过set_fact创建的,所以testvar2就好像test70的facts信息一样,可以在第二个play中引用到,而创建testvar1变量的方式则不能达到这种效果,虽然testvar2就像facts信息一样能被之后的play引用,但是在facts信息中并不能找到testvar2,只是"效果上"与facts信息相同罢了。

    前文已经总结了注册变量的用法,其实注册变量也可以在之后的play操作同一主机时被调用到,示例如下
    1. ---
    2. - hosts: test70
    3.   remote_user: root
    4.   vars:
    5.     testvar3: tv3
    6.   tasks:
    7.   - shell: "echo tv4"
    8.     register: testvar4
    9.   - debug:
    10.       msg: "{{testvar3}} -- {{testvar4.stdout}}"

    11. - hosts: test70
    12.   remote_user: root
    13.   tasks:
    14.   - name: other play get testvar4
    15.     debug:
    16.       msg: "{{testvar4.stdout}}"
    17.   - name: other play get testvar3
    18.     debug:
    19.       msg: "{{testvar3}}"
    复制代码
    执行上例的playbook时,在第二个play中获取"testvar3"时会报错,而在第二个play中获取注册变量"testvar4"时则正常,但是,注册变量中的信息是模块的返回值,这并不是我们自定义的信息,所以,如果想要在tasks中给变量自定义信息,并且在之后的play操作同一个主机时能够使用到之前在tasks中定义的变量时,则可以使用set_facts定义对应的变量。

    细心如你一定发现了,上述示例中,即使是跨play获取变量,也都是针对同一台主机,但是某些时候,我们可能想要在操作一台主机时,获取到之前操作的另一台主机中定义的变量,那么该怎样做呢?具体做法就放在下一篇文章中总结吧,这篇文章就先总结到这里,希望能够对你有所帮助。


    帖子永久地址: 

    黑帽联盟 - 论坛版权1、本主题所有言论和图片纯属会员个人意见,与本论坛立场无关
    2、本站所有主题由该帖子作者发表,该帖子作者与黑帽联盟享有帖子相关版权
    3、其他单位或个人使用、转载或引用本文时必须同时征得该帖子作者和黑帽联盟的同意
    4、帖子作者须承担一切因本文发表而直接或间接导致的民事或刑事法律责任
    5、本帖部分内容转载自其它媒体,但并不代表本站赞同其观点和对其真实性负责
    6、如本帖侵犯到任何版权问题,请立即告知本站,本站将及时予与删除并致以最深的歉意
    7、黑帽联盟管理员和版主有权不事先通知发贴者而删除本文

    您需要登录后才可以回帖 登录 | 会员注册

    发布主题 !fastreply! 收藏帖子 返回列表 搜索
    回顶部