ansible:lineinfile有几行?


162

用同样的方法还有一个模块lineinfile在一个文件中添加一条线,有没有办法来添加几行?

我不想使用模板,因为您必须提供整个文件。我只想在现有文件中添加一些内容,而不必知道文件已经包含了什么,因此模板不是一个选择。


我知道您不想使用template,但是使用lineinfile反模式。这也是一个强烈的危险信号,您“不知道文件中有什么”,这会导致未知故障的巨大风险。
tedder42

39
这不是反模式。lineinfile的重点是支持多个源管理同一文件,这有时是不可避免的。大多数配置文件具有固定的格式,而避免冲突的逻辑通常不太重要。
Doug F

我不知道我PC上的绝大多数文件都包含什么。并不意味着我想全部消灭他们!
DylanYoung

Answers:


221

您可以使用循环来做到这一点。这是一个使用with_items循环的示例:

- name: Set some kernel parameters
  lineinfile:
    dest: /etc/sysctl.conf
    regexp: "{{ item.regexp }}"
    line: "{{ item.line }}"
  with_items:
    - { regexp: '^kernel.shmall', line: 'kernel.shmall = 2097152' }
    - { regexp: '^kernel.shmmax', line: 'kernel.shmmax = 134217728' }
    - { regexp: '^fs.file-max', line: 'fs.file-max = 65536' }

确保在引号中有line =和regexp =的参数。我没有,而且我不断msg: this module requires key=value arguments。给出的示例确实具有这种正确性-我只是没有遵循该示例。
JDS 2014年

1
请问在第一次更改之前如何进行一次备份?也许item.backup?:D
tdihp

6
这可能在Ansible 2.0之前被投票通过。现在一个更好的答案是:stackoverflow.com/a/28306576/972128
kkurian

@kkurian当然,仅当您要插入时,如果您要替换时就不?
ndtreviv '18

7
@kkurian如果您例如需要向json文件中添加一些行并且不需要任何标记,则blockinfile解决方案将不起作用。尽管您可以将标记设置为“”,但ansible blockinfile仍会查找标记,找不到任何标记,然后再次插入该块。因此,没有标记的blockinfile不是等幂的,有循环的lineinfile是幂等的。
荒谬

176

您可以尝试blockinfile改用。

你可以做类似的事情

- blockinfile: |
    dest=/etc/network/interfaces backup=yes
    content="iface eth0 inet static
        address 192.168.0.1
        netmask 255.255.255.0"

8
blockinfile每当我选择使用它时,该模块的效果都非常好。我特别喜欢insertafter/ insertbefore选项的直观行为。
杰伊·泰勒

9
投票最高的答案可能是在Ansible 2.0之前,但是现在这是更正确的答案。
Willem van Ketwich '16

11
Blockinfile需要标记。有时这是没有选择的。
ceving

1
我们可以用覆盖内容blockinfile吗?
pkaramol


20

如果您需要配置一组唯一的property = value行,我建议一个更简洁的循环。例如:

- name: Configure kernel parameters
  lineinfile:
    dest: /etc/sysctl.conf
    regexp: "^{{ item.property | regex_escape() }}="
    line: "{{ item.property }}={{ item.value }}"
  with_items:
    - { property: 'kernel.shmall', value: '2097152' }
    - { property: 'kernel.shmmax', value: '134217728' }
    - { property: 'fs.file-max', value: '65536' }

使用Alix Axel建议的字典,并添加自动删除匹配的注释掉条目的功能,

- name: Configure IPV4 Forwarding
  lineinfile:
    path: /etc/sysctl.conf
    regexp: "^#? *{{ item.key | regex_escape() }}="
    line: "{{ item.key }}={{ item.value }}"
  with_dict:
    'net.ipv4.ip_forward': 1

2
如果使用with_dict,它将更加简洁。
阿里克斯·阿克塞尔

18

这是使用with_items的解决方案的无噪音版本:

- name: add lines
  lineinfile: 
    dest: fruits.txt
    line: '{{ item }}'
  with_items:
    - 'Orange'
    - 'Apple'
    - 'Banana' 

对于每个项目,如果该项目存在于fruits.txt中,则不会采取任何措施。

如果该项不存在,它将被附加到文件末尾。

十分简单。


不能与insertafter结合使用。
ceving

如果缺少多行,我希望该项目按顺序显示。如何确定附加项目的顺序?
MUY比利时

5

这并不理想,但是允许您多次调用lineinfile。结合使用insert_after,您可以获得所需的结果:

- name: Set first line at EOF (1/3)
  lineinfile: dest=/path/to/file regexp="^string 1" line="string 1"
- name: Set second line after first (2/3)
  lineinfile: dest=/path/to/file regexp="^string 2" line="string 2" insertafter="^string 1"
- name: Set third line after second (3/3)
  lineinfile: dest=/path/to/file regexp="^string 3" line="string 3" insertafter="^string 2"

5
是的,但一次仍是一行。如果我有15行,我宁愿只用一条命令添加它们。似乎不可能。
2014年

1
谢谢。似乎这仍然是在after / before之前插入多行的唯一方法。
tims

5

通过使用\nline参数,我能够做到这一点。

如果可以验证文件,并且添加一行会生成一个无效文件,这将特别有用。

就我而言,我是使用以下命令将AuthorizedKeysCommand和添加AuthorizedKeysCommandUsersshd_config

- lineinfile: dest=/etc/ssh/sshd_config line='AuthorizedKeysCommand /etc/ssh/ldap-keys\nAuthorizedKeysCommandUser nobody' validate='/usr/sbin/sshd -T -f %s'

仅添加一个选项会生成一个验证失败的文件。


12
每次运行剧本时,这都会额外创建一条线-无法正确识别该线已经存在。至少,我在Ansible 1.7.1上就是这种情况
David

1
我报告了一个错误,但是Ansible的家伙没有兴趣修复它。
ceving

1
现在有一个新的blockinfile模块应该比该解决方案更好。(docs.ansible.com/ansible/blockinfile_module.html
朋兹

1

要添加多行,您可以使用blockfile:

- name: Add mappings to /etc/hosts
  blockinfile:
    path: /etc/hosts
    block: |
      '10.10.10.10  server.example.com'
      '10.10.10.11  server1.example.com'

要添加一行,您可以使用lininfile:

- name: server.example.com in /etc/hosts
  lineinfile:
    path: /etc/hosts
    line: '192.0.2.42 server.example.com server'
    state: present

1

要添加多行,您可以使用lineinfile模块,此处with_items还包含变量vars以使其简单:)

---
- hosts: localhost  #change Host group as par inventory
  gather_facts: no
  become: yes
  vars:
    test_server: "10.168.1.1"
    test_server_name: "test-server"
    file_dest: "/etc/test/test_agentd.conf"

  - name: configuring test.conf
    lineinfile:
      dest: "{{ item.dest }}"
      regexp: "{{ item.regexp }}"
      line: "{{ item.line }}"
    with_items:
      - { dest: '"{{ file_dest }}"', regexp: 'Server=', line: 'Server="{{test_server}}"' }
      - { dest: '"{{ file_dest }}"', regexp: 'ServerActive=', line: 'ServerActive="{{test_server}}"' }
      - { dest: '"{{ file_dest }}"', regexp: 'Hostname=', line: 'Hostname="{{test_server_name}}"' }
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.