ansible:lineinfile 几行?

Posted

技术标签:

【中文标题】ansible:lineinfile 几行?【英文标题】:ansible: lineinfile for several lines? 【发布时间】:2014-08-11 14:46:34 【问题描述】:

同样的方法有一个模块lineinfile在文件中添加一行,有没有办法添加多行?

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

【问题讨论】:

我知道您不想使用template,但使用lineinfile 是antipattern。这也是一个强烈的危险信号,即您“不知道文件中有什么”,这会导致出现未知故障的巨大风险。 这不是反模式。 lineinfile 的重点是支持多个源管理同一个文件,这有时是不可避免的。大多数配置文件都有固定的格式,避免冲突的逻辑通常不会太大。 我不知道我电脑上绝大多数文件的内容;并不意味着我想把他们都用核武器炸死! 【参考方案1】:

您可以在loop 中使用lineinfile built-in。这是一个例子:

- name: Set some kernel parameters
  lineinfile:
    dest: /etc/sysctl.conf
    regexp: " item.regexp "
    line: " item.line "
  loop:
    -  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。给出的例子确实是正确的——我只是没有遵循这个例子。 请问第一次更改前如何进行单次备份?也许item.backup? :D 这可能在 Ansible 2.0 之前被投票通过。现在更好的答案是:***.com/a/28306576/972128 @kkurian 当然只有在你插入的时候,而不是在你替换的时候? @kkurian 如果您使用 blockinfile 解决方案,例如需要在 json 文件中添加一些行并且不需要任何标记。虽然您可以将标记设置为“”,但 ansible blockinfile 仍会查找标记,找不到任何标记,然后再次插入块。因此,没有标记的 blockinfile 不是幂等的,带有循环的 lineinfile 是。【参考方案2】:

您可以尝试改用blockinfile

你可以这样做

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

【讨论】:

blockinfile 模块在我每次选择使用它时都表现出色。我特别喜欢 insertafter/insertbefore 选项的直观行为。 投票率最高的答案可能是在 Ansible 2.0 之前,但现在这是更正确的答案。 Blockinfile 需要标记。这有时是没有选择的。 我们能用blockinfile覆盖内容吗? 我认为这是正确的做法。 docs.ansible.com/ansible/blockinfile_module.html【参考方案3】:

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

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

对于每个项目,如果该项目存在于 fruits.txt 中,则不执行任何操作。

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

简单易行。

【讨论】:

这个不能和insertafter结合使用。 如果缺少多行,我希望该项目出现在订单中。如何确定附加项目的顺序?【参考方案4】:

如果您需要配置一组唯一的 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 建议的 dict 并添加自动删除匹配的注释掉的条目,

- 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

【讨论】:

如果使用 with_dict 会更简洁。【参考方案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"

【讨论】:

是的,但它仍然是一次一行。如果我有 15 行,我宁愿只用一个命令来添加它们。这似乎是不可能的。 谢谢。似乎这仍然是在之后/之前插入多行的唯一方法。【参考方案6】:

我可以通过在 line 参数中使用 \n 来做到这一点。

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

就我而言,我使用以下命令将AuthorizedKeysCommandAuthorizedKeysCommandUser 添加到sshd_config

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

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

【讨论】:

这将在每次运行 playbook 时创建一个额外的行——它不能正确识别该行已经存在。至少,我在 Ansible 1.7.1 上就是这种情况 我报告了 bug,但 Ansible 人员没有兴趣修复它。 现在有一个新的 blockinfile 模块应该比那个解决方案更好。 (docs.ansible.com/ansible/blockinfile_module.html)【参考方案7】:

要添加多行,您可以使用块文件:

- 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

【讨论】:

【参考方案8】:

要添加多行,您可以使用 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"' 

【讨论】:

【参考方案9】:

要在配置文件中添加多行,您可以使用" " 而不是' ' 和转义序列\n 用于lineinfile ansible 模块中的新行:

- name: Configure core-site.xml
  lineinfile:
    path: /etc/hadoop/core-site.xml
    insertafter: '^<configuration>'
    line: "Line 1 \n Line 2 \n Line 3"

【讨论】:

以上是关于ansible:lineinfile 几行?的主要内容,如果未能解决你的问题,请参考以下文章

ansible 下lineinfile详细使用

ansible模块-lineinfile

ansible的lineinfile模块

ansible 之 lineinfile

Ansible模块lineinfile替换指定行内容多行replace及j2的shell/yaml

Ansible模块lineinfile替换指定行内容多行replace及j2的shell/yaml