zoukankan      html  css  js  c++  java
  • Ansible系列基础篇 1.7.2、PlayBook之变量

     一、变量定义及使用

     定义:变量名应该由字母、数字、下划线组成,变量名需要以字母开头,ansible内置的关键字不能作为变量名。

    1.1、基础变量

    变量基础使用示例(红色字体为关键字部分):

    ---
    - hosts: test70
      vars:
        testvar1: testfile
      remote_user: root
      tasks:
      - name: task1
        file:
          path: /testdir/{{ testvar1 }}
          state: touch
    

    1.2、定义多个变量

    方式一:

    vars:
      testvar1: testfile
      testvar2: testfile2
    

    方式二:

    vars:
      - testvar1: testfile
      - testvar2: testfile2

    方式三:

    nginx:
      conf80: /etc/nginx/conf.d/80.conf
      conf8080: /etc/nginx/conf.d/8080.conf
    

      

    1.3、属性方式定义变量

    ---
    - hosts: test70
      remote_user: root
      vars:
        nginx:   # 属性方式定义
          conf80: /etc/nginx/conf.d/80.conf
          conf8080: /etc/nginx/conf.d/8080.conf
      tasks:
      - name: task1
        file:
          path: "{{nginx.conf80}}"   # 访问方式一
          state: touch
      - name: task2
        file:
          path: "{{nginx['conf8080']}}"   # 访问方式二
          state: touch
    

      

    1.4、变量引用时 引号使用

    变量在被引用时,变量出"开头的位置,变量引用,一定要加上冒号,否则报语法错误;当变量引用并没有处于"开头的位置",则不需要加上冒号。具体用法示例如下:

        file:
          # 变量不在开头位置
          path: /testdir/{{ testvar1 }}
          state: touch
    
        file:
          # 变量在开头位置
          path: "{{nginx.conf80}}"
          state: touch
    

      

    在playbook中为模块的参数赋值时,可以使用"冒号",也可以使用"等号",当使用"等号"为模块的参数赋值时,则不用考虑引用变量时是否使用"引号"的问题,示例如下:

    ---
    - hosts: test70
      remote_user: root
      vars:
        nginx:
          conf80: /etc/nginx/conf.d/80.conf
          conf8080: /etc/nginx/conf.d/8080.conf
      tasks:
      - name: task1
        file:
          path={{nginx.conf80}}
          state=touch
      - name: task2
        file:
          path={{nginx['conf8080']}}
          state=touch
    

      

    1.5、文件中定义变量 var_files

    # cat nginx_vars.yml
    nginx:
      conf80: /etc/nginx/conf.d/80.conf
      conf8080: /etc/nginx/conf.d/8080.conf 

     在nginx_vars.yml中定义完相关变量后,即可在playbook中引入文件中的变量,在playbook中引入包含变量的文件时,需要使用"vars_files"关键字,被引入的文件需要以"- "开头,以YAML中块序列的语法引入,示例如下:

    ---
    - hosts: test70
      remote_user: root
      vars_files:
      - /testdir/ansible/nginx_vars.yml
      tasks:
      - name: task1
        file:
          path={{nginx.conf80}}
          state=touch
      - name: task2
        file:
          path={{nginx['conf8080']}}
          state=touch
    

      

     vars_files引入多个变量文件,每个被引入的文件都需要以"- "开头,示例如下:

    vars_files:
      - /testdir/ansible/nginx_vars.yml
      - /testdir/ansible/other_vars.yml
    

      

    "vars"关键字和"vars_files"关键字可以同时使用,如下

    vars:
      - conf90: /etc/nginx/conf.d/90.conf
      vars_files:
      - /testdir/ansible/nginx_vars.yml
    

    二、注册变量

    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
    

    示例结果:

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

    如果想获取上述返回信息的特定key值,则可以:

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

     

     

    三、用户输入信息的变量

    用户输入的信息,存储到变量中(默认情况下private: yes,用户输入,并不会显示,类似linux输入密码),示例代码如下:

    ---
    - hosts: test70
      remote_user: root
      vars_prompt:
        - name: "your_name"
          prompt: "What is your name"
        - name: "your_age"
          prompt: "How old are you"
      tasks:
       - name: output vars
         debug:
          msg: Your name is {{your_name}},You are {{your_age}} years old.
    

    显示用户的输入信息,示例代码如下:

      vars_prompt:
        - name: "your_name"
          prompt: "What is your name"
          private: no
        - name: "your_age"
          prompt: "How old are you"
          private: no
    

    输入变量设置默认值,示例代码如下:

    ---
    - hosts: test70
      remote_user: root
      vars_prompt:
        - name: "solution"
          prompt: "Choose the solution you want 
    
          A: solutionA
    
          B: solutionB
    
          C: solutionC
    "
          private: no
          default: A
      tasks:
       - name: output vars
         debug:
          msg: The final solution is {{solution}}.
    

      

     user模块,加密解密语法,示例代码如下:

    # user模块的password字段,会默认对密码进行加密,如果用变量传递,最后主机的密码会变成加密后的字符串,这时候需要encrypt语法糖
    ---
    - hosts: test70
      remote_user: root
      vars_prompt:
        - name: "user_name"
          prompt: "Enter user name"
          private: no
        - name: "user_password"
          prompt: "Enter user password"
      tasks:
       - name: create user
         user:
          name: "{{user_name}}"
          password: "{{user_password}}"

    entrypt依赖passlib库,需要python先安装, pip install passlib。

    ---
    - hosts: test70
      remote_user: root
      vars_prompt:
        - name: "hash_string"
          prompt: "Enter something"
          private: no
          encrypt: "sha512_crypt"
      tasks:
       - name: Output the string after hash
         debug:
          msg: "{{hash_string}}"
    

      

    还有confirm关键字进行密码二次确认

    vars_prompt:
        - name: "user_password"
          prompt: "Enter user password"
          encrypt: "sha512_crypt"
          confirm: yes
    

      

    四、通过命令传递变量

    • 命令传递变量,是在执行脚本(ansible-playbook)或命令(ansible)时,通过'--extra-vars' 或 '-e' 来传递变量
    • 命令行传入的变量的优先级要高于playbook中的变量
    • 命令传递变量,除了支持'key=vaule'的形式,还支持json的传递( ‘{'key': 'vaule', 'key2': 'vaule2'}’ )
    # 标准示例
    ansible-playbook cmdvar.yml --extra-vars "pass_var=cmdline pass var"
    # -e简化,多个变量
    ansible-playbook cmdvar.yml -e 'pass_var="test" pass_var1="test1"'
    # 传递json格式变量
    ansible-playbook cmdvar.yml -e '{"testvar":"test","testvar1":"test1"}'
    # 传递复杂json格式变量,想要获取one值,使用如下两种语法引用变量{{countlist[0]}} 或者 {{countlist.0}}
    ansible-playbook cmdvar.yml -e '{"countlist":["one","two","three","four"]}'
    # 传递文件中的变量,文件内容按照标准变量来写即可
    ansible-playbook cmdvar.yml -e "@/testdir/ansible/varfile"
    

      

    五、主机变量

     Inventory文件内主机组定义的变量,可以直接在命令或剧本上,引用变量

     可以参考本教程:https://www.cnblogs.com/wangsl1204/p/13649218.html

    六、Gathering Facts

    功能:搜集系统信息。

    参考setup debug模块使用:https://www.cnblogs.com/wangsl1204/p/14177537.html

    七、set_fact定义变量

    set_fact是一个模块,我们可以通过set_fact模块在tasks中定义变量,主要用在跨playbook之间的同一台主机变量的传递,基础示例:

    ---
    - hosts: test70
      remote_user: root
      tasks:
      - set_fact:
          testvar: "testtest"
      - debug:
          msg: "{{testvar}}"
    

    复杂方式使用,从一个task的执行结果输出,赋给set_fact变量,在后续task上执行。

    ---
    - hosts: test70
      remote_user: root
      vars:
        testvar1: test1_string
      tasks:
      - shell: "echo test2_string"
        register: shellreturn
      - set_fact:
          testsf1: "{{testvar1}}"
          testsf2: "{{shellreturn.stdout}}"
      - debug:
          msg: "{{testsf1}} {{testsf2}}"
    

      

    set_fact设置的变量,可以给同个yml文件中,不同的剧本使用,具体示例如下:

    # 执行该playbook
    # 第一个playbook中,testvar1  testvar2变量都能正常输出;
    # 第二个playbook中,testvar1输出异常,testvar2输出正常;
    # 每个play执行之前都会执行一个名为"[Gathering Facts]"的默认任务,这个任务会收集对应主机的相关信息,我们可以称这些信息为facts信息,我们已经总结过怎样通过变量引用这些facts信息,此处不再赘述,而通过set_fact模块创建的变量可以在之后play中被引用,就好像主机的facts信息可以在play中引用一样。
    # 第一个play中针对test70主机进行操作时,testvar1是通过vars关键字创建的,而testvar2是通过set_fact创建的,所以testvar2就好像test70的facts信息一样,可以在第二个play中引用到,而创建testvar1变量的方式则不能达到这种效果,虽然testvar2就像facts信息一样能被之后的play引用,但是在facts信息中并不能找到testvar2,只是"效果上"与facts信息相同罢了。
    ---
    - hosts: test70
      remote_user: root
      vars:
        testvar1: tv1
      tasks:
      - set_fact:
          testvar2: tv2
      - debug:
          msg: "{{testvar1}} ----- {{testvar2}}"
     
    - hosts: test70
      remote_user: root
      tasks:
      - name: other play get testvar2
        debug:
          msg: "{{testvar2}}"
      - name: other play get testvar1
        debug:
          msg: "{{testvar1}}"
    

    register的变量效果范围,和set_fact一样,示例代码如下:

    # 第二个playbook中,testvar3 testvar4可以正常输出
    # 第二个playbook中,testvar3不能正常输出,testvar4可以正常输出
    ---
    - hosts: test70
      remote_user: root
      vars:
        testvar3: tv3
      tasks:
      - shell: "echo tv4"
        register: testvar4
      - debug:
          msg: "{{testvar3}} -- {{testvar4.stdout}}"
     
    - hosts: test70
      remote_user: root
      tasks:
      - name: other play get testvar4
        debug:
          msg: "{{testvar4.stdout}}"
      - name: other play get testvar3
        debug:
          msg: "{{testvar3}}"
    

      

    八、内置变量

    8.1、ansible_version

    功能:获取ansble的版本号

    ansible test -m debug -a "msg={{ansible_version}}"
    

      

    8.2、hostvars

    功能:获取主机的各个变量

    假设,我想要在操作test70主机时获取到test71主机中的facts信息,示例如下:

    hostvars在操作 当前主机调用"[Gathering Facts]"任务 输出其他主机中的facts信息,示例中使用hostvars加上清单中的主机名称再加上facts的key,即可获取到对应的facts信息。如果示例中test71主机设置 ‘gather_facts: no’,则示例执行失败。

    ---
    - name: "play 1: Gather facts of test71"
      hosts: test71
      remote_user: root
     
    - name: "play 2: Get facts of test71 when operating on test70"
      hosts: test70
      remote_user: root
      tasks:
      - debug:
          msg: "{{hostvars['test71'].ansible_ens35.ipv4}}"
          #或者 msg: "{{hostvars.test71.ansible_ens35.ipv4}}"
    

      

    除了facts信息,我们还能够利用hostvars内置变量从别的主机中获取到其他类型的一些变量信息,比如,其他主机的注册变量、主机变量、组变量等信息,我们先来看一个获取其他主机的注册变量的小示例,如下:

    ---
    - hosts: test71
      remote_user: root
      gather_facts: no
      tasks:
      - shell: "echo register_var_in_play1"
        register: shellreturn
     
    - hosts: test70
      remote_user: root
      gather_facts: no
      tasks:
      - debug:
          msg: "{{hostvars.test71.shellreturn.stdout}}"
    

    如上例所示,通过hostvars内置变量可以直接获取到其他主机中的注册变量,你一定发现了,注册变量并不用像facts信息那样需要事先收集,即可直接通过hostvars跨主机被引用到,同理,如果你在清单中为test71主机配置了主机变量,或者为test71主机所在的组配置了组变量,也是可以通过hostvars直接跨主机引用的。

    play中为当前主机定义一个变量,可以在之后的play中操作其他主机时被引用到吗?那么我们来做个实验,示例如下:

    结论:不能被引用到

    ---
    - hosts: test71
      remote_user: root
      gather_facts: no
      vars:
        testvar: testvar_in_71
      tasks:
      - debug:
          msg: "{{testvar}}"
     
    - hosts: test70
      remote_user: root
      gather_facts: no
      tasks:
      - debug:
          msg: "{{hostvars.test71.testvar}}"
    

      解决上述问题,可以使用set_fact,示例如下:

    ---
    - hosts: test71
      remote_user: root
      gather_facts: no
      tasks:
      - set_fact:
          testvar: "testvar_in_71"
      - debug:
          msg: "{{testvar}}"
     
    - hosts: test70
      remote_user: root
      gather_facts: no
      tasks:
      - debug:
          msg: "{{hostvars.test71.testvar}}"
    

      

    8.3、inventory_hostname

    功能:获取到被管节点当前主机的主机名称,是Inventory文件中配置的名称(可能是IP,也可能是主机名)。

    8.4、inventory_hostname_short

    功能:与内置变量inventory_hostname类似,通过inventory_hostname_short也可以获取当前play操作的主机在清单中对应的名称,但是这个名称更加简短。无论是IP还是主机名,如果清单的主机名称中包含".",inventory_hostname_short都会取得主机名中第一个"."之前的字符作为主机的简短名称。

    8.5、play_hosts

    功能:获取到当前play所操作的所有主机的主机名列表。

    8.6、groups

    功能:获取inventory文件的分组情况,包括用户的分组、all组、单独的机器组(未分类组)。

    8.7、group_names

    功能:获取到当前主机所在分组的组名(当一台主机在多个组下,可以有多个组名)。

    8.8、inventory_dir

    功能:获取到当前ansible主机中清单文件的存放路径。

  • 相关阅读:
    html中的块级元素、行内元素
    ptyhon_opencv 图像的基本操作
    正则表达式总结 2017.1.6
    HashMap 中的 entrySet()使用方法 2016.12.28
    (转)Redis持久化的几种方式
    负数与二进制换转方法
    (转)2019JAVA面试题附答案(长期更新)
    Java后端技术面试汇总(第一套)
    (转)Dubbo服务暴露过程源码分析
    Dubbo消费方服务调用过程源码分析
  • 原文地址:https://www.cnblogs.com/wangsl1204/p/14193886.html
Copyright © 2011-2022 走看看