You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 08:02:07