ansible变量

  • 变量非常的重要

一、ansible变量

1、为什么需要变量

  • 管控的各个节点的端口不同的话,就需要定义一个变量,来规定这些端口,同一个变量即可

2、主机清单中定义变量

  • 在主机清单中写入即可

  • 在主机清单中定义的变量比ansible.cfg这个配置文件的优先级高

  • 内置的主机变量

  • ansible_user=qqq ansible_port=2222

  • ansible_become 提权

  • 主机变量和主机组变量

  • 如果主机变量和主机组变量相同的时,主机变量的优先级更高

[devops@master ansible]$ cat hosts 
[node]
node1  ansible_port=2222  # 修改了默认的端口
 
[devops@master ansible]$ ansible node1 -m ping 
node1 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python3"
    },
    "changed": false,
    "ping": "pong"
}

# 在主机清单中定义变量,只有node1主机可以使用
[devops@master ansible]$ cat hosts 
node1 webserver=nginx

[devops@master ansible]$ cat test.yml 
- hosts: node1
  tasks:
    - debug:
        var: webserver

# 主机组变量
[devops@master ansible]$ cat hosts 
node1 webserver=nginx
[server]
node1
[server:vars] # 定义主机组变量
rhelname=rhce


[devops@master ansible]$ ansible node1 -m shell -a "echo {{rhelname}}"
node1 | CHANGED | rc=0 >>
rhce

1、主机目录定义变量

  • host_vars目录下,创建以主机名命名的文件,只有这个主机才能引用这个变量文件

  • 放在主机清单目录下

[devops@master host_vars]$ pwd
/home/devops/ansible/host_vars
# 创建一个和主机名同名的变量文件,才能被node1使用
[devops@master host_vars]$ ls
node1

[devops@master ansible]$ ansible node1 -m shell -a "echo {{name}}"
node1 | CHANGED | rc=0 >>
123


2、主机组目录定义变量

  • group_vars目录下面创建以主机组命名的文件

  • 主机清单中有这个主机组的定义

[devops@master group_vars]$ pwd
/home/devops/ansible/group_vars
[devops@master group_vars]$ cat server 
age: 99

[devops@master ansible]$ ansible node1 -m shell -a "echo {{age}}"
node1 | CHANGED | rc=0 >>
99

3、剧本中定义变量

  • 更多的是在剧本中定义变量

1、vars定义变量

  • 在tasks上面定义
[devops@master ansible]$ cat t1.yaml 
- name: use vars
  hosts: node1
  vars:  # 定义变量
    name_rhel: rhel9
  tasks:
    - shell:  touch /"{{name_rhel}}"    # "{{}}" 来引用变量


#多个变量的话,最外面用单引号 里面的话每一个都要使用双引号
[devops@master ansible]$ cat test.yml 
- hosts: node1
  vars:
    name_rhel: rhel9
    hosts_9: qq
  tasks:
    - debug:
        msg: '"{{name_rhel}}""{{hosts_9}}"'
        或者  "this is {{rhel_version}} cpu is {{rhel_cpu}}"  # 都在双引号里面即可

    

1、调试变量

  • 使用debug模块

  • msg和var参数,不能在一起使用

  • msg会输出信息内容

  • var不会输出内容

[devops@master ansible]$ cat t1.yaml 
- name: use vars
  hosts: node1
  vars:
    name_rhel: rhel9
  tasks:
    - debug:
        msg: this is "{{name_rhel}}"  # "{{}}" 来引用变量

# 输出结果为

TASK [debug] ********************************************************************
ok: [node1] => {
    "msg": "this is \"rhel9\""
}


# var来引用变量
[devops@master ansible]$ cat t1.yaml 
- name: use vars
  hosts: node1
  vars:
    name_rhel: rhel9
  tasks:
    - debug:
        var: name_rhel

# 输出结果为

ok: [node1] => {
    "name_rhel": "rhel9"
}

2、vars_files定义变量

  • 引用外部的变量文件

  • 里面的内容是键值对的方式

  • 不能是列表 - 这样的

  • 在tasks上面定义引用文件

  • 里面需要保持唯一性,变量,

[devops@master ansible]$ cat vars.txt 
user:
  name: qq
  age: 99


user1:
  name: oo

user2:
   name: qq

[devops@master ansible]$ cat test.yml 
- hosts: node1
  vars_files:
    - vars.txt
  tasks:
    - debug:
        msg: "{{user.name}}"

3、注册变量

  • 通过任务的执行结果注册为一个变量

  • 根据这个返回的结果来使用变量,有的没有rc,就不能使用这个rc,会出现未定义的报错

  • register定义

[devops@master ansible]$ cat 1.yml 
- hosts: node1
  tasks:
    - shell: ls /etc/passwd
      register: get_status  # 将上面的任务执行结果注册为一个变量
    - debug:
        var: get_status


[devops@master ansible]$ ansible-playbook 1.yml 
# 得到的信息
ok: [node1] => {
    "get_status": {
        "changed": true,
        "cmd": "ls /etc/passwd",
        "delta": "0:00:00.003579",
        "end": "2025-09-19 13:23:54.236280",
        "failed": false,
        "msg": "",
        "rc": 0,  # 命令的返回值
        "start": "2025-09-19 13:23:54.232701",
        "stderr": "",  # 错误输出信息
        "stderr_lines": [],
        "stdout": "/etc/passwd", # 正确输出
        "stdout_lines": [
            "/etc/passwd"
        ]
    }
}


# 只需要看rc结果的返回值
[devops@master ansible]$ cat 1.yml 
- hosts: node1
  tasks:
    - shell: ls /etc/passwd
      register: get_status
    - debug:
        var: get_status.rc  # 查看任务是否执行成功了

[devops@master ansible]$ ansible-playbook 1.yml 
TASK [debug] **********************************************************************************
ok: [node1] => {
    "get_status.rc": "0"
}

  • 应用场景,将主机的密钥文件保存到被控节点
[devops@master ansible]$ cat 1.yml 
- hosts: node1
  tasks:
    - shell: cat /etc/ssh/ssh_host_ecdsa_key.pub
      register: get_status  # 注册变量
    - debug:
        var: get_status.stdout  # 获取这个公钥信息
    - copy:
        content: "{{get_status.stdout}}\n"  # 将这个公钥信息保存到被控节点上面
        dest: /opt/pub.key 

[root@node1 opt]# cat pub.key 
ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBGIjoUkO3DPGEks9jNTnTrFR1OXyoZVqOjFaORr/kh0IP2+UXkx9hz/wP7m9kB29pmsaMeMojrL/xGrp1xk= 

4、命令行方式来定义变量

  • -e选项

  • 在yml中直接使用变量,然后在执行剧本的时候传入变量,这样的话就非常的灵活

  • 这样的话就不会太死板了

  • 临时传入变量

  • 如果要定义多个变量就多写几个e即可

[devops@master ansible]$ ansible node1 -m debug -a "var=name" -e name=222
[WARNING]: Found variable using reserved name: name
node1 | SUCCESS => {
    "name": "222"
}


[devops@master ansible]$ cat 2.yaml 
- hosts: node1
  tasks:
    - shell: touch "{{file}}"

# 在执行的时候传入变量即可
[devops@master ansible]$ ansible-playbook 2.yaml -e file=/opt/kkk

5、fact变量(事实变量)

  • 每一次执行剧本后,就会有一个gather_facts

  • 事实变量,收集被控节点的主机信息,然后定义成一个变量

  • setup模块,可以收集被控节点的主机信息,facts参数,专门用来收集的变量,保存到facts变量

# 回收集所有信息
# ip地址,磁盘等信息
[devops@master ansible]$ ansible node1 -m setup
node1 | SUCCESS => {
    "ansible_facts": {
        "ansible_all_ipv4_addresses": [
            "192.168.50.11"
        ],

1、筛选filter

[devops@master ansible]$ ansible node1 -m setup -a "filter=ansible_all_ipv4_addresses"
node1 | SUCCESS => {
    "ansible_facts": {
        "ansible_all_ipv4_addresses": [
            "192.168.50.11"
        ],
        "discovered_interpreter_python": "/usr/bin/python3"
    },
    "changed": false
}


# 使用通配符,*
[devops@master ansible]$ ansible node1 -m setup -a "filter=ansible*addresses"
node1 | SUCCESS => {
    "ansible_facts": {
        "ansible_all_ipv4_addresses": [
            "192.168.50.11"
        ],
        "ansible_all_ipv6_addresses": [
            "fe80::539e:bd2d:62fd:dc1d"
        ],
        "discovered_interpreter_python": "/usr/bin/python3"
    },
    "changed": false
}


2、导入到一个文件中

[devops@master ansible]$ ansible node1 -m setup  > node1_facts.txt

3、引用事实变量

[devops@master ansible]$ cat 2.yaml 
- hosts: node1
  tasks:
    - debug:
         var: ansible_all_ipv4_addresses


4、禁用facts变量

  • gather_facts为no

  • 这个默认是开启的

[devops@master ansible]$ cat 2.yaml 
- hosts: node1
  gather_facts: no  # 关闭收集信息
  tasks:
    - debug:
         var: ansible_all_ipv4_addresses

# 输出信息
TASK [debug] **********************************************************************************
ok: [node1] => {
    "ansible_all_ipv4_addresses": "VARIABLE IS NOT DEFINED!"
}


5、自定义事实变量

让每一个主机都有自己的facts变量,每一个facts变量都是存放到/etc/ansible/facts.d目录下

定义的格式有要求的:ini或者yaml,文件的后缀必须是.fact结尾(ini格式的话就是网卡的配置文件的格式)

自定义facts事实变量
#创建一个自定义变量的文件,后缀为fact结尾的
[root@controller mnt]# cat userinfo.fact
[user]
name = zhangsan
age = 18
sex = boy
 
 
#创建yaml文件
#并将变量文件文件拷贝过去
[root@controller mnt]# cat userinfo.yaml
- name: user fact
  hosts: node1
  tasks:
    - name: create dir
      file:
        path: /etc/ansible/facts.d
        state: directory
    - name: copy
      copy:
        src: /mnt/userinfo.fact
        dest: /etc/ansible/facts.d
 
#引用变量自定义变量文件,会将变量的内容默认保存到ansible_load中
#自定义变量文件使用ansible_local
[root@controller mnt]# ansible node1 -m setup -a "filter=ansible_local"
node1 | SUCCESS => {
    "ansible_facts": {
        "ansible_local": {
            "userinfo": {
                "user": {
                    "age": "18",
                    "name": "zhangsan",
                    "sex": "boy"
                }
            }
        },
        "discovered_interpreter_python": "/usr/bin/python"
    },
    "changed": false
}

6、set_fact模块生成变量

  • 可以生成一个变量

  • 将多个facts变量整合一下即可

  • 将直接使用事实变量,来生成一个变量的值

# 获取版本信息
[devops@master ansible]$ cat 3.yml 
- hosts: node1
  tasks:
    - set_fact:  # 生成一个变量
        get_version: "{{ansible_distribution}}--{{ansible_distribution_version}}"
    - debug:
        var: get_version

# 输出信息
TASK [debug] **********************************************************************************
ok: [node1] => {
    "get_version": "RedHat--9.0"
}

7、lookup变量

  • 生成变量,然后后面的模块可以引用这个变量

  • 获取的信息都是主控节点的信息

  • 在某些情况,引入外部的内容,将主控节点的公钥作为变量传输到被控节点中

  • lookup从文件,命令,变量中作为变量的值

# 查看支持的
[devops@master ansible]$ ansible-doc -t lookup -l 

1、从文件读取

  • get_passwd: "{{lookup('file','/etc/passwd')}}" 将文件的内容作为变量的值
# 获取的信息都是主控节点上面的passwd文件
[devops@master ansible]$ cat 4.yml 
- hosts: node1
  tasks:
    - set_fact:
        content: "{{ lookup('file','/etc/passwd')}}"  # 将里面的内容赋值给content
    - debug:
         var: content

# 输出信息
TASK [debug] **********************************************************************************
ok: [node1] => {
    "content": "root:x:0:0:root:/root:/bin/bash\nbin:x:1:1:bin:/bin:/sbin/nologin\ndaemon:x:2:2:daemon:/sbin:/sbin/nologin\nadm:x:3:4:adm:/var/adm:/sbin/ 省略
}


# 生成了一个变量,然后将这个变量的内容拷贝到被控节点上面去

# 将密钥拷贝到被控节点上面
[devops@master ansible]$ cat 4.yml 
- hosts: node1
  tasks:
    - set_fact:
        key: "{{ lookup('file','/home/devops/.ssh/id_rsa.pub')}}"
    - copy:
        content: "{{key}}"
        dest: /opt/key.txt

2、从命令中读取

  • get_c: "{{ lookup('pipe','date +%T') }}"

  • pipe后面就是命令

[devops@master ansible]$ cat 4.yml 
- hosts: node1
  tasks:
    - set_fact:
         get_c: "{{ lookup('pipe','date +%T') }}"
    - debug:
        msg: "{{get_c}}"

# 定义变量
[devops@master test]$ cat 1.yml 
- hosts: master
  vars:
    mm: "{{ lookup('pipe','date +%T') }}"
  tasks:
    - debug:
        msg: "{{ mm }}"


# 创建用户,加密的密码
[devops@master ansible]$ cat 4.yml 
- hosts: node1
  tasks:
    - set_fact:
         get_c: "{{ lookup('pipe','openssl passwd -6 123') }}"
    - user:
        name: qqq
        password: "{{get_c}}"

3、使用env定义

  • get_c: "{{ lookup('env','HOME') }}"
[devops@master ansible]$ cat 4.yml 
- hosts: node1
  tasks:
    - set_fact:
         get_c: "{{ lookup('env','HOME') }}"
    - debug:
         var: get_c

# 输出信息
TASK [debug] **********************************************************************************
ok: [node1] => {
    "get_c": "/home/devops"
}

8、魔法变量

1、hostvars

  • 获取指定主机的变量信息,挺有用的

  • 说到底还是获取的是facts变量

# 获取node1主机的主机名
[devops@master ansible]$ cat magic.yml 
- hosts: node1
  tasks:
    - debug:
        msg: "{{ hostvars['node1'].ansible_hostname }}"

# 输出信息
ok: [node1] => {
    "msg": "node1"
}


# 获取指定主机的信息
- hosts: node1,node2
  tasks:
    - set_fact:
         node1_ip: "{{ hostvars['node1'].ansible_all_ipv4_addresses }}"
      register: get_status
    - shell: echo "{{ node1_ip }}"
    - debug:
        msg: "{{ get_status }}"

2、inventory_hostname

  • 列出当前运行的主机是谁

  • 列出的是主机清单中的主机名

  • 经常和when语句进行使用,判断是不是当前的主机名,如果不是的话,不执行

  • 是node1主机就安装nginx,是node2的话安装php

[devops@master ansible]$ cat magic.yml 
- hosts: node1
  tasks:
    - debug:
        var: ansible_hostname
      when: inventory_hostname=='node1'

# 输出信息
ok: [node1] => {
    "ansible_hostname": "node1"
}

3、groups

  • 列出主机清单中所有主机组列表

  • groups.all 列出所有的主机

  • groups.主机组 列出这个主机组中所有主机

  • group_names 会根据当前运行的主机来判断

# 获取当前的主机属于哪些组,如果在test在这个里面的会就执行
when test in group_names  # 当前运行的主机在属于test这个组的话,就执行,否则不执行,通俗点就是属于test这个组的主机执行

  • 更多的魔方变量,ansible-doc
[devops@master ansible]$ cat magic.yml 
- hosts: node1
  tasks:
    - debug:
        var: groups

  • group_names
[devops@master test]$ cat magic.yml 
- hosts: node1,node2
  tasks:
    - shell: mkdir /opt/dir1
      when: "'node' in group_names"   # 执行任务的主机属于node这个组的话就执行,也就是属于node这个组的主机执行该任务

二、总结

  • 变量的定义方式各有不同

  • 定义变量

    • vars,直接在yml中定义变量

    • vars_files,使用变量文件

    • 注册变量,register,会获取到这个任务的执行结果,使用这个任务的执行结果,比如rc返回值是否为0

    • 命令方式 -e

    • fact变量,可以直接使用

    • set_fact生成变量,使用的是事实变量

    • lookup也是,有很多中方式生成变量,从文件中,从命令中,

    • 魔方变量经常与facts中的变量配合使用,获取当前的主机名,ip地址等信息

posted @ 2025-09-15 14:29  w7nn  阅读(7)  评论(0)    收藏  举报