Loading

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 \n
      A: solutionA\n
      B: solutionB\n
      C: solutionC\n"
      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主机中清单文件的存放路径。

 

posted @ 2020-12-26 19:18  wsongl  阅读(346)  评论(0编辑  收藏  举报