黑帽联盟

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

[基础服务] ansible笔记(31):变量(六)

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

920

主题

37

听众

1364

积分

超级版主

Rank: 8Rank: 8

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

    [LV.9]以坛为家II

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

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


    在之前的文章中,我们已经总结了很多变量的用法,今天再来介绍一个引入变量的方法,使用'include_vars'引入变量,不过在介绍'include_vars'之前,我们先来回顾一下'vars_files'的用法,我们知道,通过'vars_files'可以将文件中的变量引入playbook,以便在task中使用,那么,我们先来看一个示例变量文件(注:变量文件位于ansible控制节点中,与目标主机无关),示例变量文件'/testdir/ansible/testfile'中的内容如下:
    1. testvar1: aaa
    2. testvar2: bbb
    复制代码
    如上所示,其中一共定义了两个变量,如果我们使用'vars_files'导入这两个变量,可以编写如下playbook
    1. ---
    2. - hosts: test70
    3.   remote_user: root
    4.   gather_facts: no
    5.   vars_files:
    6.   - /testdir/ansible/testfile
    7.   tasks:
    8.   - debug:
    9.       msg: "{{testvar1}}"
    复制代码
    上例中,我们调用了变量文件中的testvar1变量,输出的值为aaa,没有任何问题,但是,我们来考虑一种特殊情况,假设playbook中一共有3个任务,第1个任务调用了变量文件中的变量,第2个任务在变量文件中新增了一个变量,第3个任务能在变量文件中引用到新增的变量么,我们来试试,playbook如下
    (注:为了更加方便的操作变量文件进行测试,此处将目标主机设置为test71,主机test71为ansible控制主机)
    1. ---
    2. - hosts: test71
    3.   remote_user: root
    4.   gather_facts: no
    5.   vars_files:
    6.   - /testdir/ansible/testfile
    7.   tasks:
    8.   - debug:
    9.       msg: "{{testvar1}},{{testvar2}}"
    10.   - lineinfile:
    11.       path: "/testdir/ansible/testfile"
    12.       line: "testvar3: ccc"
    13.   - debug:
    14.       msg: "{{testvar1}},{{testvar2}},{{testvar3}}"
    复制代码
    如上例所示,我们定义了三个任务,第二个任务中,使用lineinfile模块在变量文件中增加了testvar3变量,然后在第三个任务中调用了testvar3变量,执行上例playbook,你会发现,执行出错了,因为在playbook载入vars_files对应的变量文件时,文件中只有两个变量,在执行第三个任务执行,并没有重新载入对应的变量文件,所以执行报错了,那么,聪明如你一定想到了,我们需要一种便捷的方法,能够在任务执行过程中,随时的引入变量文件,以便动态的获取到最新的变量文件内容,没错,依靠'include_vars'即可满足我们的要求,示例如下
    1. ---
    2. - hosts: test71
    3.   remote_user: root
    4.   gather_facts: no
    5.   vars_files:
    6.   - /testdir/ansible/testfile
    7.   tasks:
    8.   - debug:
    9.       msg: "{{testvar3}}"
    10.   - lineinfile:
    11.       path: "/testdir/ansible/testfile"
    12.       line: "testvar4: ddd"
    13.   - include_vars: "/testdir/ansible/testfile"
    14.   - debug:
    15.       msg: "{{testvar4}}"
    复制代码
    如上例所示,由于testvar3已经加入到了变量文件中,所以,我们在上例中的第一个任务中就能调用到testvar3,第二个任务中,我们在变量文件中新增了一个变量testvar4,第三个任务调用了'include_vars'模块,'include_vars'模块重新加载了变量文件,第四个任务中,调用了testvar4变量。
    执行上例playbook,完全可以正常执行,这就是'include_vars'模块的优势,它可以动态的以任务的方式在合适的时机引用变量文件中的变量,很方便吧。

    有些时候,变量文件可能并没有位于ansible主机中,而是位于远程主机中,所以,我们需要先把变量文件从远程主机中拉取到ansible主机中,当通过前面的task拉取到变量文件以后,也可以使用'include_vars'模块加载刚才拉取到的变量文件,以便后面的task可以使用变量文件中的变量。

    'include_vars'模块其实还有一些常用参数(这些参数大多数都是从2.2版本以后加入的),我们一起来了解一下
    先来看一个小示例,如下
    1. ---
    2. - hosts: test70
    3.   remote_user: root
    4.   gather_facts: no
    5.   tasks:
    6.   - include_vars:
    7.       file: /testdir/ansible/testfile
    8.   - debug:
    9.       msg: "{{testvar4}}"
    复制代码
    如上例所示,file参数可以指定要包含的变量文件,其实与如下写法效果相同
    1. - include_vars: "/testdir/ansible/testfile"
    复制代码
    'include_vars'还有一个小功能,'include_vars'可以把变量文件中的变量全部赋值给另外一个变量,什么意思呢?来看一个小示例,如下
    1. ---
    2. - hosts: test70
    3.   remote_user: root
    4.   gather_facts: no
    5.   tasks:
    6.   - include_vars:
    7.       file: /testdir/ansible/testfile
    8.       name: trans_var
    9.   - debug:
    10.       msg: "{{trans_var}}"
    复制代码
    执行上例playbook,debug模块输出信息如下
    1. TASK [debug] **********************************************
    2. ok: [test70] => {
    3.     "msg": {
    4.         "testvar1": "aaa",
    5.         "testvar2": "bbb",
    6.         "testvar3": "ccc",
    7.         "testvar4": "ddd"
    8.     }
    9. }
    复制代码
    可以发现,' trans_var'变量的值就是变量文件中的所有变量,没错,如你所见,我们可以使用name参数指定一个变量,然后将文件中的所有变量都赋值给这个指定的变量,当使用了name参数时,如果想要获取到文件中的某一个变量的值,则可以使用如下方法
    1.   tasks:
    2.   - include_vars:
    3.       file: /testdir/ansible/testfile
    4.       name: trans_var
    5.   - debug:
    6.       msg: "{{trans_var.testvar4}}"
    复制代码
    'include_vars'不仅能够加载指定的变量文件,还能够一次性将指定目录下的所有变量文件中的变量加载,使用dir参数即可指定对应的目录,示例如下
      tasks:
    1.   - include_vars:
    2.       dir: /testdir/ansible/test/
    3.       name: trans_var
    4.   - debug:
    5.       msg: "{{trans_var}}"
    复制代码
    上例中,使用dir参数指定了"/testdir/ansible/test/"目录,此目录中的所有变量文件都会被加载,但是在使用dir参数时,需要注意如下三点
    第一:指定目录中的所有文件的文件后缀必须是 '.yaml' 、'.yml' 、'.json'中的一种,默认只有这三种后缀是合法后缀,如果目录中存在非合法后缀的文件,执行playbook时则会报错。
    第二:如果此目录中的子目录中包含变量文件,子目录中的变量文件也会被递归的加载,而且子目录中的文件也必须遵守上述第一条规则。
    第三:dir参数与file参数不能同时使用。

    第一点与第二点都是默认设置,可以通过其他选项修改,方法如下

    当使用dir参数时,指定目录中的所有文件必须以 '.yaml' 、'.yml' 、'.json' 作为文件的后缀,如果想要手动指定合法的文件后缀名,则可以使用extensions参数指定哪些后缀是合法的文件后缀,extensions参数的值需要是一个列表,示例如下
    1.   tasks:
    2.   - include_vars:
    3.       dir: /testdir/ansible/test/
    4.       extensions: [yaml,yml,json,varfile]
    5.       name: trans_var
    6.   - debug:
    7.       msg: "{{trans_var}}"
    复制代码
    上例中extensions参数的值为 "[yaml,yml,json,varfile]",这表示指定目录中的合法文件后缀名为yaml、yml、json和varfile。

    当使用dir参数时,默认情况下会递归的加载指定目录及其子目录中的所有变量文件,如果想要控制递归的深度,则可以借助depth参数,示例如下
    1.   tasks:
    2.   - include_vars:
    3.       dir: /testdir/ansible/test/
    4.       depth: 1
    5.       name: trans_var
    6.   - debug:
    7.       msg: "{{trans_var}}"
    复制代码
    上例表示,加载"/testdir/ansible/test/"目录中的变量文件,但是其子目录中的变量文件将不会被加载,depth的值为1表示递归深度为1,默认值为0,表示递归到最底层的子目录。

    在使用dir参数时,我们还可以借助正则表达式,匹配那些我们想要加载的变量文件,比如,我们只想加载指定目录中以"var_"开头的变量文件,则可以使用如下方法
    1.   tasks:
    2.   - include_vars:
    3.       dir: /testdir/ansible/test/
    4.       files_matching: "^var_.*"
    5.       name: trans_var
    6.   - debug:
    7.       msg: "{{trans_var}}"
    复制代码
    如上例所示,使用'files_matching'参数可以指定正则表达式,当指定目录中的文件名称符合正则时,则可以被加载

    其实,不仅能够使用正则去匹配需要加载的变量文件名,还可以明确指定,哪些变量文件不能被加载,使用'ignore_files'参数可以明确指定需要忽略的变量文件名称,'ignore_files'参数的值是需要是一个列表,示例如下
    1.   tasks:
    2.   - include_vars:
    3.       dir: /testdir/ansible/test/
    4.       ignore_files: ["^var_.*",varintest.yaml]
    5.       name: trans_var
    6.   - debug:
    7.       msg: "{{trans_var}}"
    复制代码
    上例表示,加载 /testdir/ansible/test/目录中的变量文件,但是所有以"var_"开头的变量文件和varintest.yaml变量文件将不会被加载, 'files_matching'参数和'ignore_files'参数能够同时使用,当它们同时出现时,会先找出正则匹配到的文件,然后从中排除那些需要忽略的文件。

    在2.4版本以后的ansible中,当执行了include_vars模块以后,include_vars模块会将载入的变量文件列表写入到自己的返回值中,这个返回值的关键字为'ansible_included_var_files',所以,如果我们想要知道本次任务引入了哪些变量文件,则可以使用如下方法
    1.   tasks:
    2.   - include_vars:
    3.       dir: /testdir/ansible/test/
    4.     register: return_val
    5.   - debug:
    6.       msg: "{{return_val.ansible_included_var_files}}"
    复制代码

    这篇文章就总结到这里,希望能够对你有所帮助~~
    帖子永久地址: 

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

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

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