Ansible使用lineinfile模块追加主机名至文件时内容缺失
问题根源
你碰到的是多进程文件竞争导致的问题:你的playbook会对--limit指定的每台主机单独执行lineinfile任务,这些任务是并行运行的——多个进程同时打开、修改、保存newDevices.txt,部分写入操作会被覆盖,最终出现内容随机缺失的情况。lineinfile模块本身单进程下是安全的,但扛不住多进程同时操作同一个文件。
修复方案
把写入主机名的任务改成仅执行一次,通过循环遍历目标主机列表批量写入,彻底规避并行竞争。修改后的playbook如下:
- name: Setting some variables. hosts: "{{ target }}" gather_facts: no connection: local tasks: - name: Delete and recreate newDevices file. file: path: newDevices.txt state: absent run_once: true - name: Create empty newDevices file. file: path: newDevices.txt state: touch mode: '0644' run_once: true - name: Add all target devices to file in one go lineinfile: path: newDevices.txt line: "{{ item }}" loop: "{{ ansible_play_hosts_all }}" delegate_to: 127.0.0.1 run_once: true
方案说明
- 保留原有的删、建文件逻辑,用
run_once确保只执行一次 - 核心修改:
ansible_play_hosts_all变量会返回当前play实际执行的所有主机(包含--limit过滤后的结果),通过loop遍历这个列表,一次性把所有主机名写入文件,全程仅执行一次写入操作,完全避免并行竞争
更简洁的替代写法
如果不需要保留lineinfile的幂等性(比如每次都要生成全新的文件),可以直接用copy模块生成文件,效率更高:
- name: Setting some variables. hosts: "{{ target }}" gather_facts: no connection: local tasks: - name: Generate newDevices.txt with all target hosts copy: content: "{{ ansible_play_hosts_all | join('\n') }}\n" dest: newDevices.txt mode: '0644' delegate_to: 127.0.0.1 run_once: true
这个写法直接把所有主机名拼接成字符串,一次性写入文件,完全不会有竞争问题,代码也更简洁。
内容的提问来源于stack exchange,提问作者stminion001
相关产品推荐
相关产品推荐

