Ansible lineinfile模块循环遇重复项被跳过,如何强制添加所有行?
问题根源
ansible.builtin.lineinfile天生就不是用来重复添加相同行的——它的核心逻辑是保证文件里有且仅有一行指定内容,不管是循环里的重复项,还是文件里已经存在该行,它都会直接跳过,返回ok(跳过)。
解决办法:换用能处理重复行的模块
要强制把所有指定项(包括重复的echo)都添加到.bashrc里,推荐下面几种方案:
方案1:用blockinfile插入整块内容
把所有要加的行打包成一个块,一次性插入文件。块里的重复行会完整保留,还能通过标记避免重复插入整个块:
- name: 往.bashrc添加所有指定行 ansible.builtin.blockinfile: path: /home/toto/.bashrc block: | echo screenfetch echo marker: "# {mark} 自定义命令区块" insertafter: EOF
marker是用来标记这个块的起止的,下次执行Playbook时,只会检查这个块是否存在,不会重复插入整个块。如果非要每次执行都追加,删掉marker就行,但会导致文件里重复出现整个块,慎用。
方案2:用shell直接追加(无幂等性)
如果不在乎重复执行会多次追加,直接用shell命令往文件末尾写最直接:
- name: 强制把所有行追加到.bashrc ansible.builtin.shell: | echo "echo" >> /home/toto/.bashrc echo "screenfetch" >> /home/toto/.bashrc echo "echo" >> /home/toto/.bashrc
- 注意:每次跑这个Playbook,这三行都会被追加一次,文件里会越来越多重复行,只适合一次性操作。
方案3:用copy模块实现带幂等性的重复行添加
如果既要保留重复行,又不想每次执行都重复追加,可以先把要加的行拼成字符串,再通过标记替换文件里的指定区域:
- name: 拼接要添加的行 ansible.builtin.set_fact: custom_lines: | echo screenfetch echo - name: 更新.bashrc里的自定义内容 ansible.builtin.copy: dest: /home/toto/.bashrc content: "{{ lookup('file', '/home/toto/.bashrc').split('# 自定义内容开始')[0] }}# 自定义内容开始\n{{ custom_lines }}\n# 自定义内容结束" owner: toto group: toto mode: '0644'
- 原理是用
# 自定义内容开始和# 自定义内容结束标记一块区域,每次执行都会把这块区域的内容替换成你指定的custom_lines,既保留了重复行,又不会乱追加。
内容的提问来源于stack exchange,提问作者tweetysat
相关产品推荐
相关产品推荐

