ansible:複数行のlineinfile?


162

lineinfileファイルに1行を追加するモジュールがあるのと同じように、複数の行を追加する方法はありますか?

ファイル全体を提供する必要があるため、テンプレートを使用したくありません。テンプレートがオプションではないので、ファイルがすでに何を含んでいるかを必ずしも知らなくても、既存のファイルに何かを追加したいだけです。


使用したくないとのことですtemplateが、使用lineinfileアンチパターンです。また、「ファイルの内容がわからない」という強い警告であり、未知の障害の大きなリスクにつながります。
tedder42 2014年

39
それはアンチパターンではありません。lineinfileのポイントは、同じファイルを管理する複数のソースをサポートすることです。ほとんどの構成ファイルは固定形式であり、競合を回避するためのロジックは通常、それほど大きくありません。
Doug F

PC上のファイルの大部分が何であるかわかりません。それらすべてを核にしたいという意味ではありません!
DylanYoung 2018年

回答:


222

ループを使用してそれを行うことができます。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

1
最初の変更の前に単一のバックアップを行う方法を尋ねてもよいですか?多分item.backup?:D
tdihp 2016年

6
これはおそらくAnsible 2.0の前に投票されました。より良い答えは今です:stackoverflow.com/a/28306576/972128
kkurian

@kkurian差し替えるのではなく、挿入する場合にのみですか?
ndtreviv

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オプションの直感的な動作が特に気に入っています。
Jay Taylor、

9
最も投票された回答はおそらくAnsible 2.0より前でしたが、これが現在の方が正しい回答です。
Willem van Ketwich 2016年

11
Blockinfileにはマーカーが必要です。これはオプションがない場合があります。
1

1
コンテンツを上書きできますblockinfileか?
pkaramol 2017年

1
それを行うには正しい方法だと思います。docs.ansible.com/ansible/blockinfile_module.html
Paulo Victor

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の提案に従って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

2
with_dictを使用すると、より簡潔になります。
Alix Axel 2017年

18

以下は、with_itemsを使用するソリューションのノイズのないバージョンです。

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

各アイテムについて、アイテムがFruits.txtに存在する場合、アクションは実行されません。

アイテムが存在しない場合は、ファイルの最後に追加されます。

かんたん。


これはinsertafterと組み合わせることはできません。
1

複数の行が欠落している場合、アイテムを注文に表示したいと思います。アイテムが追加される順序を確認するにはどうすればよいですか?
ベルギー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
はい、それでも一度に1行です。15行ある場合は、コマンドを1つだけ追加してください。可能ではないようです。
Michael

1
ありがとう。これは、挿入後/前に複数の行を挿入する唯一の方法であるようです。
timss

5

私はそれを行うことができました \n行パラメーターで。

これは、ファイルを検証でき、1行追加すると無効なファイルが生成される場合に特に役立ちます。

私の場合、次のコマンドを使用してsshd_configにとを追加AuthorizedKeysCommandAuthorizedKeysCommandUserていました。

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

オプションの1つだけを追加すると、検証に失敗したファイルが生成されます。


12
これにより、プレイブックが実行されるたびに追加の行が作成されます。行が既に存在することは正しく認識されません。少なくとも、それがAnsible 1.7.1に私のためにケースだ
デヴィッド・

1
私はバグを報告しましたが、Ansibleの人たちはそれを修正する関心がありません。
1

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'

1行を追加するには、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_itemsvars

---
- 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}}"' }
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.