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\njoy",   #换行输出
        "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\njoy", 
        "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/)本人同意即可转载,谢谢!

你可能感兴趣的:(006.Ansible自定义变量)