• 006.Ansible自定义变量


    ansible支持变量,用于存储会在整个项目中重复使用到的一些值。以简化项目的创建与维护,降低出错的机率。

    变量的定义:

    • 变量名应该由字母、数字下划数组成
    • 变量名必须以字母开头
    • ansible内置关键字不能作为变量名

    1. 在Inventory中定义变量

    1.1. 定义主机变量

    1.1.1. 内置主机变量

    所谓内置变量其实就是ansible.cfg配置文件中的选项,在其前加上ansible_即成为内置变量。当然内置变拥有比ansible.cfg中选项更高的优先级,而且针对不同的主机,可以定义不同的值。

    # 一般连接
    ansible_ssh_host     #用于指定被管理的主机的真实IP
    ansible_ssh_port     #用于指定连接到被管理主机的ssh端口号,默认是22
    ansible_ssh_user     #ssh连接时默认使用的用户名
    
    # 特定ssh连接
    ansible_connection   #SSH连接的类型:local, ssh, paramiko,在ansible 1.2 之前默认是paramiko,后来智能选择,优先使用基于ControlPersist的ssh(如果支持的话)
    ansible_ssh_pass     #ssh连接时的密码
    ansible_ssh_private_key_file  #秘钥文件路径,如果不想使用ssh-agent管理秘钥文件时可以使用此选项
    ansible_ssh_executable  #如果ssh指令不在默认路径当中,可以使用该变量来定义其路径
    
    # 特权升级
    ansible_become      #相当于ansible_sudo或者ansible_su,允许强制特权升级
    ansible_become_user #通过特权升级到的用户,相当于ansible_sudo_user或者ansible_su_user
    ansible_become_pass # 提升特权时,如果需要密码的话,可以通过该变量指定,相当于ansible_sudo_pass或者ansible_su_pass
    ansible_sudo_exec   #如果sudo命令不在默认路径,需要指定sudo命令路径
    
    # 远程主机环境参数
    ansible_shell_executable   # 设置目标机上使用的shell,默认为/bin/sh
    ansible_python_interpreter #用来指定python解释器的路径,默认为/usr/bin/python 同样可以指定ruby 、perl 的路径
    ansible_*_interpreter      #其他解释器路径,用法与ansible_python_interpreter类似,这里"*"可以是ruby或才perl等其他语言

    下面是一个简单的示例:

    192.168.132.131 ansible_ssh_user=ansible ansible_become_user=user1  ansible_become_method=sudo ansible_become_pass="redhat" 
    192.168.132.132  ansible_python_interpreter=/usr/local/python3/bin/python3
    192.168.132.133  ntpserver=192.168.132.134 zabbixserer=192.168.132.134

    1.2 定义主机组变量

    变量也可以通过组名,应用到组内的所有成员:

    [web]
    node1
    node2
    [web:vars]
    ntpserver=192.168.132.134

    [root@node1 ansible]# vim vars_play1.yml

    - hosts: web
      tasks:
        - package:
            name:  ntpdate
            state: present
        - cron:
            name: sync time
            minute: "*/5"
            job: "ntpdate {{ ntpserver }}"

    [root@node1 ansible]# ansible-playbook   vars_play1.yml

    PLAY [web] ********************************************************************************************************
    TASK [Gathering Facts] ********************************************************************************************
    ok: [node1]
    ok: [node2]
    TASK [package] ****************************************************************************************************
    changed: [node2]
    changed: [node1]
    TASK [cron] *******************************************************************************************************
    changed: [node1]
    changed: [node2]
    PLAY RECAP ********************************************************************************************************
    node1                      : ok=3    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
    node2                      : ok=3    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0 

     检查

    [root@node1 ansible]# ansible web -m shell -a "crontab -l"

    node2 | CHANGED | rc=0 >>
    #Ansible: tectcron
    * * * * * echo `date` >> /tmp/test.txt
    #Ansible: sync time
    */5 * * * * ntpdate 192.168.132.134
    node1 | CHANGED | rc=0 >>
    #Ansible: tectcron
    * * * * * echo `date` >> /tmp/test.txt
    #Ansible: sync time
    */5 * * * * ntpdate 192.168.132.134

    变量的优先级,主机变量拥有最高的优先级

    [web]
    node1 ntpserver=ntp1.aliyun.com 
    node2
    [web:vars]
    ntpserver=192.168.132.134

    2. 在Playbook中定义变量

    2.1. 变量的定义方式

    2.1.1. 通过vars关键字定义

    拥有比主机和主机组更高的优先级

    前面的一个示例:

    - hosts: web
      vars: 
        ntpserver: ntp2.aliyun.com
      tasks:
        - package:
            name:  ntpdate
            state: present
        - cron:
            name: sync time
            minute: "*/5"
            job: "ntpdate {{ ntpserver }}"

    [root@node1 ansible]# ansible-playbook vars_play1.yml

    [root@node1 ansible]# ansible web -m shell -a "crontab -l"

    node1 | CHANGED | rc=0 >>
    #Ansible: tectcron
    * * * * * echo `date` >> /tmp/test.txt
    #Ansible: sync time
    */5 * * * * ntpdate ntp2.aliyun.com
    node2 | CHANGED | rc=0 >>
    #Ansible: tectcron
    * * * * * echo `date` >> /tmp/test.txt
    #Ansible: sync time
    */5 * * * * ntpdate ntp2.aliyun.com

    自定义变量,debug调试

    - hosts: web
      vars: 
        ntpserver: ntp2.aliyun.com
        # users: [{"name":"natasha","gender"},{"name":"tom","gender":"male" }]
        users:
          - name: natasha
            gender: famale
          - name: tom
            gender: male
      tasks:
        - debug:
            msg: "print users: {{ users }}"
        - debug:
            var: users

    [root@node1 ansible]# ansible-playbook vars_play1.yml

    PLAY [web] ************************************************************************************************************************************
    TASK [debug] **********************************************************************************************************************************
    ok: [node1] => {
        "msg": "print users: [{u'gender': u'famale', u'name': u'natasha'}, {u'gender': u'male', u'name': u'tom'}]"
    }
    ok: [node2] => {
        "msg": "print users: [{u'gender': u'famale', u'name': u'natasha'}, {u'gender': u'male', u'name': u'tom'}]"
    }
    TASK [debug] **********************************************************************************************************************************
    ok: [node1] => {
        "users": [
            {
                "gender": "famale", 
                "name": "natasha"
            }, 
            {
                "gender": "male", 
                "name": "tom"
            }
        ]
    }
    ok: [node2] => {
        "users": [
            {
                "gender": "famale", 
                "name": "natasha"
            }, 
            {
                "gender": "male", 
                "name": "tom"
            }
        ]
    }

    2.1.2. 通过vars_files关键字引入变量文件

    下面是一个简单示例:

    - hosts: web
      vars_files:
        - ntp.yml
        - users.yml
      tasks:
        - package:
            name:  ntpdate
            state: present
        - cron:
            name: sync time
            minute: "*/5"
            job: "ntpdate {{ ntpserver }}"
        - debug:
            msg: "print users: {{ users }}"
        - debug:
            var: users

    [root@node1 ansible]# vim ntp.yml

    ntpserver: ntp3.aliyun.com

    [root@node1 ansible]# vim users.yml

    users:
      - name: natasha
        gender: famale
      - name: tom
        gender: male

    变量的定义格式是成键值对出现的,键值对之间可以嵌套,最终形成一个大字典,效果和前面一样

    2.2 在playbook中通过host_vars和group_vars目录定义变量

    定义inventory

    demo5.example.com
    [datacenter1]
    demo1.example.com
    demo2.example.com
    
    [datacenter2]
    demo3.example.com
    demo4.example.com
    
    [webserver]
    demo1.example.com demo2.example.com demo3.example.com [mysqlserver] demo4.example.com demo5.example.com [datacenters:children] datacenter1 datacenter2

    创建两个目录

    [root@node1 ansible]# mkdir group_vars
    [root@node1 ansible]# mkdir host_vars

    这两个目录用于存放变量的配置文件

    主机组使用变量

    [root@node1 ansible]# vim group_vars/datacenter1
    package: "tomacat1"
    [root@node1 ansible]# vim group_vars/datacenter2
    package: "tomacat2"
    [root@node1 ansible]# vim group_vars/datacenters
    package: "tomacat3"
    [root@node1 ansible]# vim group_vars/mysqlserver
    package: "mysql"

    主机变量

    [root@node1 ansible]# vim host_vars/demo1.example.com
    package: "nginx1"
    [root@node1 ansible]# vim host_vars/demo3.example.com
    package: "nginx3"
    [root@node1 ansible]# vim host_vars/demo5.example.com
    package: "nginx5"

    目录结构

    [root@node1 ansible]# tree 
    .
    ├── ansible.cfg
    ├── group_vars
    │   ├── datacenter1
    │   ├── datacenter2
    │   ├── datacenters
    │   └── mysqlserver
    ├── hosts
    ├── host_vars
    │   ├── demo1.example.com
    │   ├── demo3.example.com
    │   └── demo5.example.com
    ├── inventory
    └── roles

    [root@node1 ansible]# cat datacenter.yml

    - hosts:  datacenter1
      tasks:
        - name: fetch vars
          debug:
             msg: "{{ package}}"

    执行

    TASK [fetch vars] *****************************************************************************************************************************
    ok: [demo1.example.com] => {
        "msg": "nginx1"
    }
    ok: [demo2.example.com] => {
        "msg": "tomacat1"
    }

    [root@node1 ansible]# vim datacenter.yml

    - hosts: all
      tasks:
        - name: fetch vars
          debug:
             msg: "{{ package}}"

    root@node1 ansible]# ansible-playbook datacenter.yml 

    TASK [fetch vars] *****************************************************************************************************************************
    ok: [demo4.example.com] => {
        "msg": "tomcat2"
    }
    ok: [demo5.example.com] => {
        "msg": "nginx5"
    }
    ok: [demo1.example.com] => {
        "msg": "nginx1"
    }
    ok: [demo2.example.com] => {
        "msg": "tomacat1"
    }
    ok: [demo3.example.com] => {
        "msg": "nginx3"
    }

    如果主机组定义的变量与主机冲突,主机变量优先级最高

    2.3  注册变量

    在有些时候,可能需要将某一条任务执行的结果保存下来,以便在接下的任务中调用或者做些判断。可以通过register关键字来实现将某一任务结果保存为一个变量。

    注册变量的应用场景:

    • 在一台远端的服务器获取一个目录下的一列表的文件,然后下载这些文件
    • 在handler执行之前,发现前面一个task发生了changed,然后执行一个指定的task
    • 获取远端服务器的ssh key的内容,构建出known_hosts文件

    [root@node1 ansible]# vim var_test.yml

    - hosts: demo5.example.com
      tasks:
        - name: list /home
          shell: ls /home
          register: list
        - debug:
            var: list

    [root@node1 ansible]# ansible-playbook var_test.yml

    PLAY [demo5.example.com] **********************************************************************************************************************
    TASK [Gathering Facts] ************************************************************************************************************************
    ok: [demo5.example.com]
    TASK [list /home] *****************************************************************************************************************************
    changed: [demo5.example.com]
    TASK [debug] **********************************************************************************************************************************
    ok: [demo5.example.com] => {
        "list": {
            "changed": true, 
            "cmd": "ls /home", 
            "delta": "0:00:00.005802", 
            "end": "2020-01-28 13:09:38.768490", 
            "failed": false, 
            "rc": 0,    #命令执行的正常的返回
            "start": "2020-01-28 13:09:38.762688", 
            "stderr": "", 
            "stderr_lines": [], 
            "stdout": "ansible
    joy",   #换行输出
            "stdout_lines": [      #这个包含也是的是正常的返回
                "ansible", 
                "joy"
            ]
        }
    }
    PLAY RECAP ************************************************************************************************************************************
    demo5.example.com          : ok=3    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0 

    当shell执行报错,错误可以使用ignore_error忽略,继续执行

    [root@node1 ansible]# vim var_test.yml

    - hosts: demo5.example.com
      tasks:
        - name: list /home
          shell: ls /home
          register: list
        - shell: error_test
          register: error
          ignore_errors: True
        - debug:
            var: list
        - debug:
            var: error

    [root@node1 ansible]# ansible-playbook var_test.yml

    PLAY [demo5.example.com] **********************************************************************************************************************
    TASK [Gathering Facts] ************************************************************************************************************************
    ok: [demo5.example.com]
    TASK [list /home] *****************************************************************************************************************************
    changed: [demo5.example.com]
    TASK [shell] **********************************************************************************************************************************
    fatal: [demo5.example.com]: FAILED! => {"changed": true, "cmd": "error_test", "delta": "0:00:00.004308", "end": "2020-01-28 13:21:53.726688", "msg": "non-zero return code", "rc": 127, "start": "2020-01-28 13:21:53.722380", "stderr": "/bin/sh: error_test: command not found", "stderr_lines": ["/bin/sh: error_test: command not found"], "stdout": "", "stdout_lines": []}
    ...ignoring
    TASK [debug] **********************************************************************************************************************************
    ok: [demo5.example.com] => {
        "list": {
            "changed": true, 
            "cmd": "ls /home", 
            "delta": "0:00:00.005806", 
            "end": "2020-01-28 13:21:53.151761", 
            "failed": false, 
            "rc": 0,     #正常返回
            "start": "2020-01-28 13:21:53.145955", 
            "stderr": "", 
            "stderr_lines": [], 
            "stdout": "ansible
    joy", 
            "stdout_lines": [
                "ansible", 
                "joy"
            ]
        }
    }
    TASK [debug] **********************************************************************************************************************************
    ok: [demo5.example.com] => {
        "error": {
            "changed": true, 
            "cmd": "error_test", 
            "delta": "0:00:00.004308", 
            "end": "2020-01-28 13:21:53.726688", 
            "failed": true, 
            "msg": "non-zero return code", 
            "rc": 127,    #命令不存在返回
            "start": "2020-01-28 13:21:53.722380", 
            "stderr": "/bin/sh: error_test: command not found",     #找到不到命令
            "stderr_lines": [
                "/bin/sh: error_test: command not found"
            ], 
            "stdout": "", 
            "stdout_lines": []
        }
    }
    PLAY RECAP ************************************************************************************************************************************
    demo5.example.com          : ok=5    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=1   

    2.4 通过命令行设置变量

    - hosts: '{{ hosts }}'
      remote_user: '{{ user }}'
      tasks:
        - debug: 
            var: hosts
        - debug:
            var: user

    [root@node1 ansible]# ansible-playbook var_test.yml --extra-vars "hosts=demo5.example.com user=ansible"  

    或者

    [root@node1 ansible]# ansible-playbook var_test.yml --extra-vars '{"hosts":"demo5.example.com","user":"ansible"}'

    TASK [debug] **********************************************************************************************************************************
    ok: [demo5.example.com] => {
        "hosts": "demo5.example.com"
    }
    
    TASK [debug] **********************************************************************************************************************************
    ok: [demo5.example.com] => {
        "user": "ansible"
    }

    2.5 变量的使用和调试

    定义一个变量文件

    [root@node1 ansible]# vim users.yml

    users:
      - name: natash
        gender: female
        hobby:
          - swimming
          - running
      - name: tom
        gender: male
        hobby:
          - football
          - basketball
          - sleepping

    [root@node1 ansible]# vim use_users.yml

    - hosts: demo5.example.com
      vars_files:                  #调用变量文件
        - users.yml
      tasks:
        - debug:
            var: users             #获取users变量的信息结构等

    [root@node1 ansible]# ansible-playbook use_users.yml

    TASK [debug] **********************************************************************************************************************************
    ok: [demo5.example.com] => {    #user变量的结构
        "users": [    #列表有序   
            {
                "gender": "female", 
                "hobby": [
                    "swimming", 
                    "running"
                ], 
                "name": "natash"
            }, 
            {
                "gender": "male", 
                "hobby": [
                    "football", 
                    "basketball", 
                    "sleepping"
                ], 
                "name": "tom"
            }
        ]
    }

    获取user当中,第一个用户的第一个爱好

    - hosts: demo5.example.com
      vars_files:
        - users.yml
      tasks:
        - debug:
            var: users[0].hobby[0]            #第一个用户的第一个爱好
        - debug:
            msg: "{{ users[1].hobby[2] }}"    #第二个用户的第三个爱好

    执行输出

    TASK [debug] **********************************************************************************************************************************
    ok: [demo5.example.com] => {
        "users[0].hobby[0]": "swimming"
    }
    
    TASK [debug] **********************************************************************************************************************************
    ok: [demo5.example.com] => {
        "msg": "sleepping"
    }

    重新定义变量

    [root@node1 ansible]# vim users.yml 

    users:
      natash:
        - name: natash
          gender: female
          hobby:
            - swimming
            - running
      tom:
        - name: tom
          gender: male
          hobby:
            - football
            - basketball
            - sleepping

    [root@node1 ansible]# vim use_users.yml 

    - hosts: demo5.example.com
      vars_files:
        - users.yml
      tasks:
        - debug:
            var: users.natash[0].hobby[0]
        - debug:
            msg: "{{ users.tom[0].hobby }}"   #获取所有爱好

    [root@node1 ansible]# ansible-playbook use_users.yml 

    TASK [debug] **********************************************************************************************************************************
    ok: [demo5.example.com] => {
        "users.natash[0].hobby[0]": "swimming"
    }
    
    TASK [debug] **********************************************************************************************************************************
    ok: [demo5.example.com] => { 
        "msg": [
            "football", 
            "basketball", 
            "sleepping"
        ]
    }

    另外的引用变量方式

        - debug:
            var: users.natash.0.hobby.0
        - debug:
            msg: "{{ users.tom.0.hobby }}"
        - debug:
            msg: "{{ users['tom'][0]['hobby'] }}"

    2.6 关于debug介绍

    关于输出的debug部分重点说明如下:

    • login: 变量名,其值为一个字典
    • changed:ansible基于此来判断是否发生了状态改变
    • cmd:被调用的命令
    • failed:是否运行失败
    • rc:返回值,0代表正常,非0代表异常
    • stderr:如果出现异常,会在这里显示错误输出
    • stderr_lines:按行分割的错误输出
    • stdout:如果指令正常运行,则在这里输出返回结果
    • stdout:按行分割的返回结果

    需要说明的是,通过register注册的变量的结果并不是一成不变的,在不确定返回值的情况下,尽量调试看看输出结果。

    关于debug的更多用法说明:

    调试模块,用于在调试中输出信息
    常用参数:

    • msg:调试输出的消息
    • var:将某个变量传递给debug模块,debug会直接将其打印输出
    • verbosity:debug的级别

     博主声明:本文的内容来源主要来自誉天教育晏威老师,由本人实验完成操作验证,需要的博友请联系誉天教育(http://www.yutianedu.com/),获得官方同意或者晏老师(https://www.cnblogs.com/breezey/)本人同意即可转载,谢谢!

  • 相关阅读:
    求n的元素的最大最小值
    输出一个集合的所有子集,从长到短
    树的各种操作java
    几个笔试题目总结
    小知识不断补充
    java、C语言实现数组模拟栈
    LearnHowToThink
    Android中的this、Activity、Context等
    Android已上线应用开源分享中(第二季)
    Android已上线应用开源分享中(第一季)
  • 原文地址:https://www.cnblogs.com/zyxnhr/p/12807344.html
Copyright © 2020-2023  润新知