Ansible 读取文件.note
一、Ansible读取文件:
·万能读取法:
这个方法不论文件中写了什么,都能读取到
## 这个name是变量名称,可以随便定义
- set_fact:
name: "{{ lookup('file', '/data/ansible/users.json') }}"
用这个方法所有格式的文件都能直接读取,然后在后面用 | [方法] 来处理不同格式的文件
1)json 文件:
# 使用 | from_json
2)yaml、yml文件:
# 使用 | from_yaml
·如果一个 yaml 文件中包含多个 yaml:
## 用 --- 来表示不同的 yaml
# 例如:
---
name: user1
age: 20
---
name: user2
age: 21
3)csv文件:
这个方法与直接使用 read_csv模块是一样的
# 使用 | community.general.from_csv
## 必须写 community.general.
直接使用 read_csv 文件:

·旧方法:
1、读取 .csv 文件:

要将 .csv文件中第一行的标题 username,password 手动删掉,否则创建用户时会报错,因为uid字段只接受数字,这里第一行直接就是‘uid’字符是会报错的
1、read_csv 模块实际上会将csv文件读取输出为 列表嵌套字典,读取时通过遍历列表,然后再使用 fieldnames定义的字典的键,来调用字典的值
2、fieldnames: 下的字段时可以自定义的,它定义的就是我们下面调用的字典的键
3、password_hash('sha512') 用于加密密码,如果不使用它,直接输入密码,会导致密码在 /etc/shadow 中是明文存在的,不安全,而且会导致用户无法登录
4、这里必须配置 update_password: on_create ,只有在创建用户时才更新密码,否则的话没有幂等性,因为每次执行时生成的密码哈希值都不一样,就会导致每次执行都会更新密码,状态都是 changed
ansible-doc read_csv:


fieldnames 和 delimiter 属性应该是可选的
---
- name: Read CSV File
hosts: deb-node-1
gather_facts: false
tasks:
# 任务1:读取CSV文件
# 目的:从CSV文件中加载用户数据
- name: Read CSV File
# 使用community.general集合中的read_csv模块
read_csv:
# CSV文件路径(位于当前剧本的相对路径,也可以使用绝对路径)
path: users.csv
# 自定义CSV文件的列名(字段名),这些名称都是可以自定义的,你写 1,2,3,4 都行
# 这些名称必须与CSV文件中的列顺序一致,并且会按顺序匹配,例如第一列就匹配到‘username’字典中,第二列就匹配到‘passowrd’字典中,有多少‘列’就要有多少个,否则没有匹配到的列都会被归为 ‘null’这个字典键中
fieldnames: username,password,uid,email
# 指定CSV文件的分隔符为逗号
delimiter: ','
# 将读取结果保存到users变量中
register: users
# 在控制节点(localhost)上执行此任务
# 因为CSV文件在控制节点上,不在目标主机上
delegate_to: localhost
# 任务2:创建用户账户
# 目的:根据CSV数据创建用户账户
- name: Create users
# 使用Ansible内置的user模块管理用户账户
user:
# 设置用户名(从CSV的username列获取)
name: "{{ item.username }}"
# 设置用户ID(从CSV的uid列获取)
uid: "{{ item.uid }}"
# 设置用户备注信息(从CSV的email列获取)
comment: "{{ item.email }}"
# 设置用户密码(使用SHA512哈希加密)
# password_hash过滤器将明文密码转换为安全的哈希值
password: "{{ item.password | password_hash('sha512') }}"
# 设置用户的默认shell为/bin/bash
shell: /bin/bash
# 密码更新策略:on_create表示只在创建用户时设置密码
# 如果用户已存在,则不更新密码(实现密码设置的幂等性)
update_password: on_create
# 用户状态:present表示确保用户存在(创建或更新)
state: present
# 循环处理CSV文件中的每一行数据
loop: "{{ users.list }}"·测试效果:



2、读取 yaml 文件:
方式一:使用 set_fact + lookup + from_yaml
文件内容:


测试:



方式二:使用 loop + lookup + from_yaml
写为剧本变量,使用时只需要调用变量,然后再使用 loop遍历:

执行查看:

直接在任务中调用(这个方式只写到了这里,后续要写就跟前面的set_fact一样了):

执行测试:

方式三:使用 include_vars + set_fact
---
- name: read
# hosts: LEAF-SW-03,LEAF-SW-04,SPINE-SW-01
hosts: all:!LEAF-SW-01:!LEAF-SW-02
# hosts为“all”,但是排除“LEAF-SW-01” 和 “LEAF-SW-02”
gather_facts: False
tasks:
- name:
include_vars:
file: /etc/ansible/data/interfaces_info.yml
name: yaml
- name: Set fact
# 先使用 with_dict 遍历字典,再使用set_fact注册变量,将结果保存至“fact”中
## 这里使用的 set_fact 是关键
set_fact:
fact: "{{ item.value }}"
with_dict: "{{ yaml }}"
when: item.key == inventory_hostname
- name: Enable Switch Interface
ios_config:
lines:
- no shutdown
- no switchport
parents: "interface {{ item.name }}"
when:
# 使用 when 排除“Loopback”接口 and “inventory_hostname”必须等同于指定的交换机
- item.name != "Loopback0"
- inventory_hostname == "LEAF-SW-03" or inventory_hostname == "LEAF-SW-04" or inventory_hostname == "SPINE-SW-01" or inventory_hostname == "SPINE-SW-02"
with_items:
# 使用 with_items 遍历列表,然后进行操作
- "{{ fact.interface }}"
- name: Config other Interfaces
# 再配置IP地址
ios_config:
lines:
- no shutdown
- "description {{ item.description }}"
- "ip address {{ item.ipv4.address }} {{ item.ipv4.subnet_mask }}"
parents: "interface {{ item.name }}"
when: '"ipv4" in item'
# 当遍历的变量中存在"IPv4"时,才运行该剧本
with_items:
- "{{ fact.interface }}"
- name: Config SPINE Vlan
# 进行创建 vlan
ios_config:
lines:
- no shutdown
- "description {{ item.description }}"
- switchport mode access
- "switchport access vlan {{ item.vlan }}"
parents: "interface {{ item.name }}"
before:
# 在 所有操作之前,先将接口恢复至默认,并且创建 vlan
- "default interface {{ item.name }}"
- "vlan {{ item.vlan }}"
when: "'vlan' in item"
# 当遍历的变量中存在"vlan"时,才运行该剧本
with_items:
- "{{ fact.interface }}"
3、读取 json、xml 文件:
1)普通方式 include_vars:
