如何在远程Windows服务器而非Ansible本地机读取解析CSV文件?
解决Windows远程主机执行Ansible Playbook时read_csv模块加载失败问题
原Playbook及背景
原本用于在localhost执行的Playbook,核心逻辑是从共享目录拉取CSV文件到本地,再读取处理数据:
- name: Fetch file fetch: src: \\10.14.2.130\shared\folder\Data\{{ filename }} dest: /var/lib/awx/projects/Windows/ flat: yes delegate_to: 10.12.201.60 become: yes become_method: runas become_user: SYSTEM - name: Initialise data list set_fact: data_list: [] delegate_to: localhost - name: Read input file read_csv: path: "{{ filename }}" key: FirstName fieldnames: FirstName,LastName,EmailAddress delimiter: ',' register: userdata delegate_to: localhost - name: Extract the list set_fact: data_list: "{{ data_list + [{ 'FirstName': item.FirstName, 'LastName': item.LastName, 'EmailAddress': item.EmailAddress }] }}" loop: "{{ userdata | community.general.json_query('dict.[*][0]') }}" - name: Set fact for data_list set_fact: data_list: "{{ data_list[1:] }}"
由于第一个fetch任务失败,无法将CSV文件拉取到localhost,于是修改Playbook,改为先把文件复制到Windows远程主机(10.12.201.60),再在该主机上读取处理。
修改后的Playbook及报错
- name: copy file win_copy: src: \\10.14.2.130\shared\folder\Data\{{ filename }} dest: C:/ remote_src: true delegate_to: 10.12.201.60 become: yes become_method: runas become_user: SYSTEM - name: Initialise data list set_fact: data_list: [] - name: Read input file read_csv: path: C:\{{ filename }} key: FirstName fieldnames: FirstName,LastName,EmailAddress delimiter: ',' register: userdata delegate_to: 10.12.201.60 - name: Extract the list set_fact: data_list: "{{ data_list + [{ 'FirstName': item.FirstName, 'LastName': item.LastName, 'EmailAddress': item.EmailAddress }] }}" loop: "{{ userdata | community.general.json_query('dict.[*][0]') }}" - name: Set fact for data_list set_fact: data_list: "{{ data_list[1:] }}"
运行后出现报错:
fatal: [10.12.201.60]: FAILED! => { "msg": "The module read_csv was redirected to community.general.read_csv, which could not be loaded." }
原因分析
read_csv模块属于community.general集合,是基于Python编写的Ansible模块。通过WinRM连接的Windows远程节点默认使用PowerShell执行模块,无法直接运行Python模块(除非在Windows上额外配置Python环境并适配Ansible连接),因此将read_csv任务委托到Windows主机时会加载失败。
解决方案
方案一:拉回CSV到localhost处理(推荐)
将文件复制到Windows主机后,再拉回控制节点(localhost),利用控制节点的Python环境和已安装的community.general集合完成CSV读取和处理:
- name: copy file to Windows host win_copy: src: \\10.14.2.130\shared\folder\Data\{{ filename }} dest: C:/ remote_src: true delegate_to: 10.12.201.60 become: yes become_method: runas become_user: SYSTEM - name: Fetch CSV file back to localhost fetch: src: C:\{{ filename }} dest: ./{{ filename }} flat: yes delegate_to: 10.12.201.60 - name: Initialise data list set_fact: data_list: [] delegate_to: localhost - name: Read input file on localhost read_csv: path: ./{{ filename }} key: FirstName fieldnames: FirstName,LastName,EmailAddress delimiter: ',' register: userdata delegate_to: localhost - name: Extract the list set_fact: data_list: "{{ data_list + [{ 'FirstName': item.FirstName, 'LastName': item.LastName, 'EmailAddress': item.EmailAddress }] }}" loop: "{{ userdata | community.general.json_query('dict.[*][0]') }}" delegate_to: localhost - name: Remove header row from data_list set_fact: data_list: "{{ data_list[1:] }}" delegate_to: localhost
方案二:用PowerShell在Windows主机处理CSV
如果必须在Windows主机上完成CSV处理,可以使用Windows原生的PowerShell命令替代read_csv模块,无需依赖Python:
- name: copy file to Windows host win_copy: src: \\10.14.2.130\shared\folder\Data\{{ filename }} dest: C:/ remote_src: true delegate_to: 10.12.201.60 become: yes become_method: runas become_user: SYSTEM - name: Read CSV with PowerShell win_shell: | Import-Csv -Path "C:\{{ filename }}" -Header FirstName,LastName,EmailAddress -Delimiter ',' | ConvertTo-Json register: csv_output delegate_to: 10.12.201.60 - name: Parse CSV output to data_list set_fact: data_list: "{{ csv_output.stdout | from_json | list }}" - name: Remove header row(若CSV本身自带表头,可删除此步骤) set_fact: data_list: "{{ data_list[1:] }}"
内容的提问来源于stack exchange,提问作者Blitzden
相关产品推荐
相关产品推荐

