Ansible新手求教:如何从CSV文件向MySQL插入数据?
如何用Ansible将CSV文件数据插入MySQL数据库
问题描述
我是Ansible新手,正在通过案例学习相关知识。我已编写可正常运行的Ansible Playbook,能够连接MySQL数据库并执行SELECT查询。现在希望实现从/tmp/report.csv文件读取数据并插入到MySQL数据库中,请问该如何实现?
当前可用的Ansible Playbook
--- - hosts: localhost gather_facts: false #become: true tasks: - name: 执行SELECT查询 community.mysql.mysql_query: login_host: sqltest-lb-fm-in.dbaas.domain.com login_user: devops_baseline_db login_password: ********* login_port: 3307 login_db: mydb ca_cert : mydomain-SHA256-Root-CA.crt query: SELECT * FROM Inventory register: output - debug: msg: "{{ output }}"
/tmp/report.csv示例内容
Date,Hostname/IP,OS-Version,Package-Name,Pre-installed-Package-Status,Current-Installed-Version,Post-installed-Package-Status,log-loc 2022-12-15,10.109.20.12,12.5,curl,up-to-date,7.60.0-11.49.1,up-to-date,http://hostname/log_dir/ 2022-12-15,10.109.20.12,12.5,libcurl4-32bit,up-to-date,7.60.0-11.49.1,up-to-date,http://hostname/log_dir/ 2022-12-15,10.109.20.12,12.5,libcurl4,up-to-date,7.60.0-11.49.1,up-to-date,http://hostname/log_dir/ 2022-12-15,10.109.20.12,12.5,libtiff5,up-to-date,4.0.9-44.56.1,up-to-date,http://hostname/log_dir/
解决方案
1. 确认目标表结构
确保MySQL中的Inventory表(或指定的目标表)字段与CSV列对应,字段类型匹配。示例对应关系如下:
Date→date(DATE类型)Hostname/IP→hostname_ip(VARCHAR类型,长度按需设置)OS-Version→os_version(VARCHAR类型)Package-Name→package_name(VARCHAR类型)Pre-installed-Package-Status→pre_installed_status(VARCHAR类型)Current-Installed-Version→current_version(VARCHAR类型)Post-installed-Package-Status→post_installed_status(VARCHAR类型)log-loc→log_loc(VARCHAR类型)
如果表尚未创建,可添加如下任务创建表:
- name: 创建Inventory表(如果不存在) community.mysql.mysql_query: login_host: sqltest-lb-fm-in.dbaas.domain.com login_user: devops_baseline_db login_password: ********* login_port: 3307 login_db: mydb ca_cert : mydomain-SHA256-Root-CA.crt query: | CREATE TABLE IF NOT EXISTS Inventory ( date DATE, hostname_ip VARCHAR(255), os_version VARCHAR(50), package_name VARCHAR(255), pre_installed_status VARCHAR(50), current_version VARCHAR(50), post_installed_status VARCHAR(50), log_loc VARCHAR(255) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
2. 读取CSV文件内容
使用read_csv模块读取CSV文件,将内容转换为Ansible可处理的列表变量:
- name: 读取/tmp/report.csv文件 ansible.builtin.read_csv: path: /tmp/report.csv delimiter: ',' register: csv_data
3. 批量插入数据到MySQL
通过community.mysql.mysql_query模块结合循环,将CSV中的每一行数据插入数据库:
- name: 批量插入CSV数据到Inventory表 community.mysql.mysql_query: login_host: sqltest-lb-fm-in.dbaas.domain.com login_user: devops_baseline_db login_password: ********* login_port: 3307 login_db: mydb ca_cert : mydomain-SHA256-Root-CA.crt query: | INSERT INTO Inventory (date, hostname_ip, os_version, package_name, pre_installed_status, current_version, post_installed_status, log_loc) VALUES (%s, %s, %s, %s, %s, %s, %s, %s) args: - "{{ item.Date }}" - "{{ item['Hostname/IP'] }}" - "{{ item['OS-Version'] }}" - "{{ item['Package-Name'] }}" - "{{ item['Pre-installed-Package-Status'] }}" - "{{ item['Current-Installed-Version'] }}" - "{{ item['Post-installed-Package-Status'] }}" - "{{ item['log-loc'] }}" loop: "{{ csv_data.list }}" loop_control: label: "{{ item['Package-Name'] }}" # 循环时仅显示包名,简化输出
完整Playbook示例
--- - hosts: localhost gather_facts: false tasks: - name: 创建Inventory表(如果不存在) community.mysql.mysql_query: login_host: sqltest-lb-fm-in.dbaas.domain.com login_user: devops_baseline_db login_password: ********* login_port: 3307 login_db: mydb ca_cert : mydomain-SHA256-Root-CA.crt query: | CREATE TABLE IF NOT EXISTS Inventory ( date DATE, hostname_ip VARCHAR(255), os_version VARCHAR(50), package_name VARCHAR(255), pre_installed_status VARCHAR(50), current_version VARCHAR(50), post_installed_status VARCHAR(50), log_loc VARCHAR(255) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; - name: 读取/tmp/report.csv文件 ansible.builtin.read_csv: path: /tmp/report.csv delimiter: ',' register: csv_data - name: 批量插入CSV数据到Inventory表 community.mysql.mysql_query: login_host: sqltest-lb-fm-in.dbaas.domain.com login_user: devops_baseline_db login_password: ********* login_port: 3307 login_db: mydb ca_cert : mydomain-SHA256-Root-CA.crt query: | INSERT INTO Inventory (date, hostname_ip, os_version, package_name, pre_installed_status, current_version, post_installed_status, log_loc) VALUES (%s, %s, %s, %s, %s, %s, %s, %s) args: - "{{ item.Date }}" - "{{ item['Hostname/IP'] }}" - "{{ item['OS-Version'] }}" - "{{ item['Package-Name'] }}" - "{{ item['Pre-installed-Package-Status'] }}" - "{{ item['Current-Installed-Version'] }}" - "{{ item['Post-installed-Package-Status'] }}" - "{{ item['log-loc'] }}" loop: "{{ csv_data.list }}" loop_control: label: "{{ item['Package-Name'] }}"
注意事项
- 确保Ansible控制节点已安装
community.mysql集合,可通过ansible-galaxy collection install community.mysql安装。 - 替换Playbook中的数据库密码为实际密码,或使用Ansible Vault加密密码提升安全性。
- 若CSV数据量较大,可改用批量插入语法(
INSERT INTO ... VALUES (...), (...), (...))提升效率。
内容的提问来源于stack exchange,提问作者saravanan jothilingam
相关产品推荐
相关产品推荐

