Playbook变量的使用
2023-12-21 16:40:59
    		目录
 
  为了能够写出更实用的playbook,需要在playbook中使用变量。下面来讲解playbook中常见的变量。本章实验都在/home/lduan/demo2下操作,先把 demo2目录创建出来并 把ansible.cfg和 hosts拷贝进去,命令如下。  
 
 
  
 [bdqn@RHEL813 ~]$ mkdir demo2
[bdqn@RHEL813 ~]$ cp ansible.cfg hosts demo2/
[bdqn@RHEL813 ~]$ cd demo2
[bdqn@RHEL813 demo2]$ ls
ansible.cfg  hosts
[bdqn@RHEL813 demo2]$ 1.手动定义变量
通过vars来定义变量,vars和 tasks对齐。定义变量的格式如下。
vars:
 变量1: 值1
 变量2: 值2
  ... 
 定义变量时,不可有重复的变量,否则后面定义的变量的值会覆盖前面定义的变量的值,如下所示。? 
 
vars:
 aa: value1
 bb: value2
 aa: value3
 ...?这里aa重复定义了,所以aa的值最终是value3。
引用变量时用 {{变量名}} ,大括号内侧两边是否有空格是无所谓的,如下所示。?
  {{变量名}}
  {{ 变量名 }}
  {{ 变量名 }}
  {{ 变量名 }}?练习1:写一个名称为1.yaml的playbook,里面定义以下3个变量。
 
 myname1=tom  
 
 
 myname2=tom2  
 
 
 myname3=tom3  
 
 
 然后打印mynamel的值,命令如下。  
 
[bdqn@RHEL813 demo2]$ cat  1.yaml 
---
- hosts: server2
  vars:
          myname1: tom1
          myname2: tom2
          myname3: tom3
  tasks:
          - name: 打印某个变量
            debug: msg="变量myname1的值是{{myname1}}"
[bdqn@RHEL813 demo2]$ 
?运行此playbook,命令如下。
[bdqn@RHEL813 demo2]$ ansible-playbook 1.yaml 
PLAY [server2] **********************************************************************************************************************
TASK [Gathering Facts] **************************************************************************************************************
ok: [server2]
TASK [打印某个变量] ***********************************************************************************************************************
ok: [server2] => {
    "msg": "变量myname1的值是tom1"
}
PLAY RECAP **************************************************************************************************************************
server2                    : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
[bdqn@RHEL813 demo2]$ 
 
 可以看到,打印了myname1的值为 tom1。 
 
 
定义变量时,同一个变量定义多次,后面定义的生效,修改1.yaml的内容如下。?
[bdqn@RHEL813 demo2]$ cat 1.yaml 
---
- hosts: server2
  vars:
          myname1: tom1
          myname2: tom2
          myname3: tom3
          myname1: tom3
  tasks:
          - name: 打印某个变量
            debug: msg="变量myname1的值是{{myname1}}"
[bdqn@RHEL813 demo2]$ 
 
 这里定义了两次 mynamel 这个变量,第一次定义的值为toml,第二次定义的值为  
 
 
 tom3。下面运行此playbook查看结果,如下所示。 
 
[bdqn@RHEL813 demo2]$ ansible-playbook 1.yaml 
[WARNING]: While constructing a mapping from /home/bdqn/demo2/1.yaml, line 4, column 11, found a duplicate dict key (myname1). Using
last defined value only.
PLAY [server2] **********************************************************************************************************************
TASK [Gathering Facts] **************************************************************************************************************
ok: [server2]
TASK [打印某个变量] ***********************************************************************************************************************
ok: [server2] => {
    "msg": "变量myname1的值是tom3"
}
PLAY RECAP **************************************************************************************************************************
server2                    : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
[bdqn@RHEL813 demo2]$ 
 
 因为mynamel重复定义了两次,所以运行此playbook时会有提示,意思是变量重复定义  
 
 
 了,且后面定义的myname1生效,打印的结果为 tom3。 
 
 
2.变量文件
如果定义的变量太多,可以把变量拿出来单独放在一个文件中,然后在playbook中通过vars_files引用此变量文件,那么就可以直接使用此变量文件中的变量了,就像变量文件中的变量直接在YAML文件中定义似的,这样更方便管理。
?例如,创建文件vars.yaml,内容如下。
[bdqn@RHEL813 demo2]$ cat vars.yaml 
myv1: aaa
myv2: bbb
myv3: ccc
[bdqn@RHEL813 demo2]$
  ?修改1.yaml的内容如下。 
 
 
[bdqn@RHEL813 demo2]$ cat 1.yaml 
---
- hosts: server2
  vars_files:
          - vars.yaml
  vars:
          myname1: tom1
          myname2: tom2
          myname3: tom3
          myname1: tom3
  tasks:
          - name: 打印某个变量
            debug: msg="变量myname1的值是{{myname1}}"
          - name: 打印变量myv1的值
            debug: msg='变量myv1的值是{{myv1}}'
[bdqn@RHEL813 demo2]$ 
 
  这里通过vars_files来引用变量文件 vars.yaml,然后打印变量myvl的值,运行结果如下。 
 
 
  
 [bdqn@RHEL813 demo2]$ ansible-playbook 1.yaml 
PLAY [server2] **********************************************************************************************************************
TASK [Gathering Facts] **************************************************************************************************************
ok: [server2]
TASK [打印某个变量] ***********************************************************************************************************************
ok: [server2] => {
    "msg": "变量myname1的值是tom1"
}
TASK [打印变量myv1的值] *******************************************************************************************************************
ok: [server2] => {
    "msg": "变量myv1的值是aaa"
}
PLAY RECAP **************************************************************************************************************************
server2                    : ok=3    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
[bdqn@RHEL813 demo2]$ 
3.字典变量
 
 所谓字典(dictionaries简写为dict),就是存储多个变量的容器,可以把字典理解为一个木桶,里面存放了很多个变量。如图31-1所示,两个木桶xx和yy,里面分别存储了3个变量: aa=1,bb=2,cc=3 
 
 

 
 同一个字典中定义的多个变量不可有重复值,否则后面定义的变量会覆盖前面定义的变量。 
 
 
  要是引用木桶中的变量,必须指定是哪个木桶中的变量。例如,要引用木桶xx中的变量  
 
 
  
  aa,则使用xx.aa 
 
 
  
字典是在vars下定义的,语法如下。
字典名:
  var1: value2
  var2: value2
  ...注意在字典中定义这一个个变量时,变量前面是不加“-”的,且定义变量没有先后顺序。
 
 通过“字典名.变量名”这种格式来引用变量,看下面的例子。  
 
[bdqn@RHEL813 demo2]$ cat 2.yaml 
---
- hosts: server2
  vars:
          dict1:
                  myv1: aaa
                  myv2: bbb
                  myv3: ccc
          dict2:
                  myv1: 111
                  myv2: 222
                  myv3: 333
  tasks:
          - name: 打印第一个变量
            debug: msg="{{dict1.myv1}}"
[bdqn@RHEL813 demo2]$ 
 
 这里定义了两个字典dict1和 dict2,里面分别有3个变量,最后通过dict1.myvl引用了字  
 
 
 典dick1中的变量myvl。通过ansible-playbook 2.yaml运行的结果应该为aaa,如下所示。 
 
 
[bdqn@RHEL813 demo2]$ ansible-playbook 2.yaml 
PLAY [server2] **********************************************************************************************************************
TASK [Gathering Facts] **************************************************************************************************************
ok: [server2]
TASK [打印第一个变量] **********************************************************************************************************************
ok: [server2] => {
    "msg": "aaa"
}
PLAY RECAP **************************************************************************************************************************
server2                    : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
[bdqn@RHEL813 demo2]$ 
 
  如果在同一个字典中出现了相同的变量名,则后面定义的变量的值会覆盖前面定义的变量的值。 
 
 
  
 4.列表变量
 
  列表变量和字典变量比较容易弄混。下面来看一个例子,定义一个员工表,里面有3个员工,每个员工通过以下3个属性记录。 
 
 
 
 (1)uname:记录用户名。  
 
 
 (2)age:记录年龄。  
 
 
 (3)sex:记录性别。 
 
 
  ? 这个员工表的内容如下。 
 
 
 employee:
 uname: lisi
 age: 22
 sex: man
 uname: wangwu
 age: 24
 sex: man
 uname: xiaohua
 age: 21
 sex: wuman 
 为了看得清楚,这里把每个用户用空白行隔开了。每个用户都是由3个变量组成的一个整体,这个整体是员工表employee的一个元素。所以,这个员工表有3个元素,即3个人。 
 
 
 
  每个元素都有uname,所以列表employee共有3个uname,但是这3个uname不应该是  
 
 
  
  冲突的,因为它们分别属于不同的人 
 
 
  
  
   但是为了防止误会,每个元素的第一个变量前都加上一个“-”,表示它是这个元素的第  
  
 
   
   一个变量。所以,员工表改成如下内容。 
  
 
   
   employee:
 ‐ uname: lisi
 age: 22
 sex: man
 ‐ uname: wangwu
 age: 24
 sex: man
 ‐ uname: xiaohua
 age: 21
 sex: wuman 
    这样看起来就清晰了很多,这里employee就是一个列表 
   
 
    
    
     那如果想获取某个元素(某个员工)的信息该怎么办呢?可以通过employee[n]来获取,  
    
 
     
     这里的n叫作下标,下标从0开始。  
    
 
     
     
      例如,要获取第一个用户的信息,则使用employee[0]即可,employee[0]得到的值如  
     
 
      
      下。  
     
 
      
     uname: lisi
age: 22
sex: man 
       可以看到,这是由3个变量组成的,这3个变量组成了一个字典,即employee[0]就是一个字典。如果想获取第一个用户的用户名,则可以通过employee[0].uname来获取。 
      
 
      
 所以,员工表employee是由3个字典组成的;employee[0]、employee[1]、employee[2] 
 
 
列表和字典的不同如下。
 
 (1)列表的每个元素的第一个变量都是以“-”开头。  
 
 
 (2)字典的每个变量前面都不带“-”。 
 
 
练习1:判断下面的aa1和aa2是列表还是字典。aa1? ? ? ? ? ? ?aa2- xx: v1? ? ? ? xx: v1- yy: v2? ? ? ? yy: v2
这里左边的aa1是列表,每个元素中仅有一个变量,右边的aa2是字典。 ?
 
 练习2:写一个名称为3-list.yaml 的playbook,定义一个用户列表,里面包含3个用户,每  
 
 
 个用户由uname、sex、age组成,命令如下。  
 
 
[bdqn@RHEL813 demo2]$ cat 3-list.yaml 
---
- hosts: server2
  vars:
          users:
                  - uname: tom
                    sex: men
                    age: 19
                  - uname: bob
                    sex: men
                    age: 20
                  - uname: mary
                    sex: women
                    age: 22
  tasks:
          - name: 打印一个变量
            debug: msg={{ users[2] }}
[bdqn@RHEL813 demo2]$ 
 
  这里列表users定义了3个元素,现在要获取第3个元素用users[2]来表示,运行结果如下 
 
 
  
 [bdqn@RHEL813 demo2]$ ansible-playbook 3-list.yaml 
PLAY [server2] **********************************************************************************************************************
TASK [Gathering Facts] **************************************************************************************************************
ok: [server2]
TASK [打印一个变量] ***********************************************************************************************************************
ok: [server2] => {
    "msg": {
        "age": 22,
        "sex": "women",
        "uname": "mary"
    }
}
PLAY RECAP **************************************************************************************************************************
server2                    : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
[bdqn@RHEL813 demo2]$ 
 
   如果要获取第3个用户的用户名,修改3-list.yaml的内容如下。 
  
 
   
 [bdqn@RHEL813 demo2]$ cat 3-list.yaml 
---
- hosts: server2
  vars:
          users:
                  - uname: tom
                    sex: men
                    age: 19
                  - uname: bob
                    sex: men
                    age: 20
                  - uname: mary
                    sex: women
                    age: 22
  tasks:
          - name: 打印一个变量
            debug: msg={{ users[2].uname }}
[bdqn@RHEL813 demo2]$ 
 
 运行此playbook,命令如下 
 
 
[bdqn@RHEL813 demo2]$ ansible-playbook 3-list.yaml 
PLAY [server2] **********************************************************************************************************************
TASK [Gathering Facts] **************************************************************************************************************
ok: [server2]
TASK [打印一个变量] ***********************************************************************************************************************
ok: [server2] => {
    "msg": "mary"
}
PLAY RECAP **************************************************************************************************************************
server2                    : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
[bdqn@RHEL813 demo2]$ 
 
  定义列表时,也可以直接写值不写变量,通过如下方式来定义。  
 
 
listname:
 ‐ var1
 ‐ var2
 ‐ var3
 ...?这种定义变量的方式可以换成如下内容。
listname: [var1,var2,var3,...]5.数字变量的运算
 
 在YAML 文件中定义的变量,其值如果是数字,则可以进行数学运算。常见的数学运算  
 
 
 符包括+(加)、-(减)、*(乘)、/(除)、**(次方) 
 
 
 
  练习:写一个名称为4-vars,yaml 的 playbook,定义了变量aa,值为3,然后求aa*2和  
 
 
  
  aa的3次方,命令如下。  
 
 
 [bdqn@RHEL813 demo2]$ cat 4-list.yaml 
---
- hosts: server2
  vars:
          aa: 3
  tasks:
          - name: 3乘2的值
            debug: msg={{aa*2}}
          - name: 3的3次方
            debug: msg="{{3**3}}"
[bdqn@RHEL813 demo2]$  
   运行此playbook,命令如下。 
  
 
   
  [bdqn@RHEL813 demo2]$ ansible-playbook 4-list.yaml 
PLAY [server2] **********************************************************************************************************************
TASK [Gathering Facts] **************************************************************************************************************
ok: [server2]
TASK [3乘2的值] ************************************************************************************************************************
ok: [server2] => {
    "msg": "6"
}
TASK [3的3次方] ************************************************************************************************************************
ok: [server2] => {
    "msg": "27"
}
PLAY RECAP **************************************************************************************************************************
server2                    : ok=3    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
[bdqn@RHEL813 demo2]$ 
6.注册变量
 
    在playbook中用shell模块执行某个系统命令后,在结果中是不会显示这个命令结果的,这  
   
 
    
    个和在命令行中用ansible命令调用shell模块不一样。 
   
 
    
    
     练习:写一个 playbook,在里面执行系统命令hostname,命令如下。 
    
 
     
    [bdqn@RHEL813 demo2]$ cat 5-regl.yaml 
---
- hosts: server2
  tasks:
          - name: 执行一个操作系统的命令
            shell: 'hostname'
[bdqn@RHEL813 demo2]$ 
      运行此playbook,命令如下 
     
 
      
     [bdqn@RHEL813 demo2]$ ansible-playbook 5-regl.yaml 
PLAY [server2] **********************************************************************************************************************
TASK [Gathering Facts] **************************************************************************************************************
ok: [server2]
TASK [执行一个操作系统的命令] ******************************************************************************************************************
changed: [server2]
PLAY RECAP **************************************************************************************************************************
server2                    : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
[bdqn@RHEL813 demo2]$ 
 
       可以看到,没有任何输出。如果想查看这个shell命令的结果,可以把shell 命令的结果保存在一个变量中,这个变量就是注册变量,然后打印这个变量的值即可。修改5-reg1.yaml的内容如下 
      
 
       
      [bdqn@RHEL813 demo2]$ cat 5-regl.yaml 
---
- hosts: server2
  tasks:
          - name: 执行一个操作系统的命令
            shell: 'hostname'
            register: aa
          - name: 打印注册变量aa的值
            debug: msg={{aa}}
[bdqn@RHEL813 demo2]$ 运行此playbook,命令如下。
[bdqn@RHEL813 demo2]$ ansible-playbook 5-regl.yaml 
PLAY [server2] **********************************************************************************************************************
TASK [Gathering Facts] **************************************************************************************************************
ok: [server2]
TASK [执行一个操作系统的命令] ******************************************************************************************************************
changed: [server2]
TASK [打印注册变量aa的值] *******************************************************************************************************************
ok: [server2] => {
    "msg": {
        "changed": true,
        "cmd": "hostname",
        "delta": "0:00:00.002696",
        "end": "2023-12-21 11:22:46.403782",
        "failed": false,
        "rc": 0,
        "start": "2023-12-21 11:22:46.401086",
        "stderr": "",
        "stderr_lines": [],
        "stdout": "RHEL8",
        "stdout_lines": [
            "RHEL8"
        ]
    }
}
PLAY RECAP **************************************************************************************************************************
server2                    : ok=3    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
[bdqn@RHEL813 demo2]$ 
 
        结果中msg后面的内容就是aa的值,可以看到aa就是一个字典。其中cmd是执行的系统  
       
 
        
        命令,rc是此命令的返回值,stdout表示此命令的结果。 
       
 
        
        
         所以,如果只获取这个命令的结果,只要打印字典aa中的 stdout 变量即可。修改5-  
        
 
         
         regl.yam1的内容如下。 
        
 
         
        [bdqn@RHEL813 demo2]$ cat 5-regl.yaml 
---
- hosts: server2
  tasks:
          - name: 执行一个操作系统的命令
            shell: 'hostname'
            register: aa
          - name: 打印注册变量aa的值
            debug: msg={{aa.stdout}}
[bdqn@RHEL813 demo2]$ 
运行此playbook,命令如下。
[bdqn@RHEL813 demo2]$ ansible-playbook 5-regl.yaml 
PLAY [server2] **********************************************************************************************************************
TASK [Gathering Facts] **************************************************************************************************************
ok: [server2]
TASK [执行一个操作系统的命令] ******************************************************************************************************************
changed: [server2]
TASK [打印注册变量aa的值] *******************************************************************************************************************
ok: [server2] => {
    "msg": "RHEL8"
}
PLAY RECAP **************************************************************************************************************************
server2                    : ok=3    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
 
          这里正确的显示了hostname的值为RHEL8 
         
 
          
         7.facts变量
 
          ansible通过setup模块是可以获取到被管理主机的所有信息的,这些信息都是以变量的方式存在,这些变量称为facts,前面在setup模块中已经介绍过了。现在写一个名称为6-fact.yaml的playbook,用于打印server2的IP和主机名,命令如下 
         
 
          
         [bdqn@RHEL813 demo2]$ cat 6-fact.yaml 
---
- hosts: server2
  vars:
          list1: ['aaa: ']
  tasks:
          - name: 打印IP
            debug: msg={{ansible_default_ipv4.address}}
          - name: 打印主机名
            debug: msg={{ansible_fqdn}}
[bdqn@RHEL813 demo2]$ 
 
           这里打印 IP 用到的fact变量是 ansible default ipv4.address,打印主机名用到的fact变  
          
 
           
           量是 ansible_fqdn,运行结果如下。 
          
 
           
          [bdqn@RHEL813 demo2]$ ansible-playbook 6-fact.yaml 
PLAY [server2] **********************************************************************************************************************
TASK [Gathering Facts] **************************************************************************************************************
ok: [server2]
TASK [打印IP] *************************************************************************************************************************
ok: [server2] => {
    "msg": "192.168.103.14"
}
TASK [打印主机名] ************************************************************************************************************************
ok: [server2] => {
    "msg": "RHEL8"
}
PLAY RECAP **************************************************************************************************************************
server2                    : ok=3    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
[bdqn@RHEL813 demo2]$ 
 
            这里显示 server2的 IP 是192.168.103.14,主机名是RHEL8。  
           
 
            
           8.内置变量groups
 
            在 ansible 中,除用户手动去定义一些变量外,还有一些内置的变量,这些变量不需要用户定义就可以直接使用。 
           
 
            
            
             groups用于列出清单文件中所有定义的主机组及里面的主机,看下面的例子。 
            
 
             
            [bdqn@RHEL813 demo2]$ cat 7-group.yaml 
---
- hosts: server2
  tasks:
          - name: xxx
            debug: msg={{groups}}
[bdqn@RHEL813 demo2]$ 
 
              运行此playbook,命令如下。 
             
 
              
             [bdqn@RHEL813 demo2]$ ansible-playbook 7-group.yaml 
PLAY [server2] **********************************************************************************************************************
TASK [Gathering Facts] **************************************************************************************************************
ok: [server2]
TASK [xxx] **************************************************************************************************************************
ok: [server2] => {
    "msg": {
        "all": [
            "server2",
            "server3"
        ],
        "db": [
            "server2",
            "server3"
        ],
        "ungrouped": []
    }
}
PLAY RECAP **************************************************************************************************************************
server2                    : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
[bdqn@RHEL813 demo2]$ 
 
               这里显示了清单文件中所有的主机组及里面的主机信息。 
              
 
               
               
                如果只想列出某个主机组,可以通过“groups['主机组名]”或“groups.主机组名”来表  
               
 
                
                示。修改7-group.yaml的内容如下。  
               
 
                
               [bdqn@RHEL813 demo2]$ cat 7-group.yaml 
---
- hosts: server2
  tasks:
          - name: xxx
            debug: msg={{groups['db']}}
[bdqn@RHEL813 demo2]$ 
 
                 这里只显示主机组db中的主机,运行结果如下。     		
    		
    			文章来源:https://blog.csdn.net/S483374558/article/details/135124014
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!
    	本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!