Bagaimana cara membuat file kosong dengan Ansible?

115

Apa cara termudah untuk membuat file kosong menggunakan Ansible? Saya tahu saya dapat menyimpan file kosong ke dalam filesdirektori dan kemudian menyalinnya ke host jarak jauh, tetapi saya merasa itu agak tidak memuaskan.

Cara lain adalah dengan menyentuh file di host jarak jauh:

- name: create fake 'nologin' shell
  file: path=/etc/nologin state=touch owner=root group=sys mode=0555

Tapi kemudian file tersebut disentuh setiap kali, muncul sebagai garis kuning di log, yang juga tidak memuaskan ...

Apakah ada solusi yang lebih baik untuk masalah sederhana ini?

dokaspar
sumber

Jawaban:

189

Dokumentasi modul file mengatakan

Jika state=file, file TIDAK akan dibuat jika tidak ada, lihat modul salin atau template jika Anda menginginkan perilaku itu.

Jadi kami menggunakan modul salin, menggunakan force=nountuk membuat file kosong baru hanya jika file tersebut belum ada (jika file tersebut ada, isinya dipertahankan).

- name: ensure file exists
  copy:
    content: ""
    dest: /etc/nologin
    force: no
    group: sys
    owner: root
    mode: 0555

Ini adalah solusi deklaratif dan elegan.

René Pijl
sumber
15
@ ÁkosVandra: Sebenarnya tidak. Lihat: force: no.
palacsint
Terima kasih - ini adalah solusi yang jauh lebih baik daripada file / touch atau jawaban stat / file yang diterima, dan mudah dilakukan dengan "with_items"
Realis
Jawaban bagus, penasaran tentang bagaimana cara membuat dua file kosong menggunakan konstruksi yang sama dengan yang Anda berikan?
Tasdik Rahman
Apakah ada cara untuk membuatnya membuat direktori induk jika tidak ada, atau apakah saya perlu melakukannya secara terpisah?
falsePockets
Anda perlu memastikan direktori induk ada dan dapat ditulis. Lihat stackoverflow.com/questions/22844905/…
René Pijl
37

Sesuatu seperti ini (menggunakan statmodul terlebih dahulu untuk mengumpulkan data tentangnya dan kemudian memfilter menggunakan kondisional) seharusnya berfungsi:

- stat: path=/etc/nologin
  register: p

- name: create fake 'nologin' shell
  file: path=/etc/nologin state=touch owner=root group=sys mode=0555
  when: p.stat.exists is defined and not p.stat.exists

Sebagai alternatif, Anda mungkin dapat memanfaatkan changed_whenfungsionalitas tersebut.

ceejayoz
sumber
20
mungkin harus: "when: not p.stat.exists"
piro
28

Opsi lain, menggunakan modul perintah:

- name: Create file
  command: touch /path/to/file
  args:
    creates: /path/to/file

Argumen 'create' memastikan bahwa tindakan ini tidak dilakukan jika file tersebut ada.

Leynos
sumber
5
Anda harus menghindari perintah sebanyak mungkin karena tidak idempoten. ryaneschinger.com/blog/…
redshark1802
4
@ redark1802 Setuju. Meskipun dalam kasus ini, tugasnya adalah idempoten, karena tidak akan dijalankan jika "/ path / to / file" sudah ada. Saya pikir solusi René Pijl adalah yang lebih mungkin dari tiga jawaban teratas, dan pasti yang harus Anda gunakan jika Anda perlu mengatur kepemilikan, mode, dll.
Leynos
15

Berdasarkan jawaban yang diterima, jika Anda ingin file diperiksa izinnya pada setiap proses, dan ini berubah sesuai jika file tersebut ada, atau cukup buat file jika tidak ada, Anda dapat menggunakan yang berikut ini:

- stat: path=/etc/nologin
  register: p

- name: create fake 'nologin' shell
  file: path=/etc/nologin 
        owner=root
        group=sys
        mode=0555
        state={{ "file" if  p.stat.exists else "touch"}}
AllBlackt
sumber
3
Jawaban ini luar biasa karena fleksibilitas yang diberikannya kepada Anda dalam menentukan atribut file dari sebuah file jika tidak ada.
Dejay Clayton
10

file: path=/etc/nologin state=touch

Sepadan penuh dengan sentuhan (baru di 1.4+) - gunakan stat jika Anda tidak ingin mengubah stempel waktu file.

jalmasi
sumber
3
Ini bukan idempoten, tanggal file akan diubah pada setiap eksekusi dari pedoman yang memungkinkan.
Jérôme B
3
@ Jérôme B Baru di Ansible 2.7: Anda dapat membuatnya idempoten dengan file: path=/etc/nologin state=touch modification_time=preserve access_time=preserve.
GregV
8

modul file menyediakan cara untuk menyentuh file tanpa mengubah waktunya.

- name: Touch again the same file, but dont change times this makes the task idempotent
  file:
    path: /etc/foo.conf
    state: touch
    mode: u+rw,g-wx,o-rwx
    modification_time: preserve
    access_time: preserve

Referensi: https://docs.ansible.com/ansible/latest/modules/file_module.html

Ravi Kulkarni
sumber
Ini adalah jawaban yang benar untuk kemungkinan 2.7+, namun informasi penting itu hilang di dalamnya.
Honza
3

Ternyata saya tidak memiliki reputasi yang cukup untuk menempatkan ini sebagai komentar, yang akan menjadi tempat yang lebih tepat untuk ini:

Kembali. Jawaban AllBlackt, jika Anda lebih suka format multiline Ansible Anda perlu menyesuaikan kutipannya state(Saya menghabiskan beberapa menit mengerjakan ini, jadi semoga ini mempercepat orang lain),

- stat:
    path: "/etc/nologin"
  register: p

- name: create fake 'nologin' shell
  file:
    path: "/etc/nologin"
    owner: root
    group: sys
    mode: 0555
    state: '{{ "file" if  p.stat.exists else "touch" }}'
Andrew Richards
sumber
0

Untuk membuat file di mesin jarak jauh dengan perintah ad-hoc

ansible client -m file -a"dest=/tmp/file state=touch"

Mohon koreksi saya jika saya salah

vajrala chakradhar reddy
sumber
0

Diubah jika file tidak ada. Buat file kosong.

- name: create fake 'nologin' shell
  file:
    path: /etc/nologin
    state: touch
  register: p
  changed_when: p.diff.before.state == "absent"
Dmitry Balashov
sumber
0

Kombinasi dua jawaban, dengan twist. Kode akan terdeteksi sebagai diubah, ketika file dibuat atau izin diperbarui.

- name: Touch again the same file, but dont change times this makes the task idempotent
  file:
    path: /etc/foo.conf
    state: touch
    mode: 0644
    modification_time: preserve
    access_time: preserve
  changed_when: >
    p.diff.before.state == "absent" or
    p.diff.before.mode|default("0644") != "0644"

dan versi yang juga mengoreksi pemilik dan grup serta mendeteksinya sebagai berubah saat memperbaiki ini:

- name: Touch again the same file, but dont change times this makes the task idempotent
  file:
    path: /etc/foo.conf
    state: touch
    state: touch
    mode: 0644
    owner: root
    group: root
    modification_time: preserve
    access_time: preserve
  register: p
  changed_when: >
    p.diff.before.state == "absent" or
    p.diff.before.mode|default("0644") != "0644" or
    p.diff.before.owner|default(0) != 0 or
    p.diff.before.group|default(0) != 0
Roch Bourdon
sumber
ansible 2.7+ only - itu harus disebutkan.
Honza