Jak stworzyć pusty plik w Ansible?

115

Jaki jest najłatwiejszy sposób utworzenia pustego pliku za pomocą Ansible? Wiem, że mogę zapisać pusty plik wfiles katalogu, a następnie skopiować go do zdalnego hosta, ale wydaje mi się to niezadowalające.

Innym sposobem jest dotknięcie pliku na zdalnym hoście:

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

Ale potem plik jest dotykany za każdym razem, pokazując żółtą linię w dzienniku, co również jest niezadowalające ...

Czy istnieje lepsze rozwiązanie tego prostego problemu?

dokaspar
źródło

Odpowiedzi:

189

Dokumentacja modułu plików mówi

Jeśli state=fileplik NIE zostanie utworzony, jeśli nie istnieje, zobacz moduł kopiowania lub szablonu, jeśli chcesz to zachowanie.

Używamy więc modułu kopiowania, używając force=nodo tworzenia nowego pustego pliku tylko wtedy, gdy plik jeszcze nie istnieje (jeśli plik istnieje, jego zawartość jest zachowana).

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

To deklaratywne i eleganckie rozwiązanie.

René Pijl
źródło
15
@ ÁkosVandra: Właściwie nie. Zobacz: force: no.
palacsint
Dzięki - jest to o wiele lepsze rozwiązanie niż plik / dotyk lub akceptowana stat / odpowiedź z pliku i jest łatwe do zrobienia z "with_items"
Realist
Świetna odpowiedź, byłeś ciekawy, jak można utworzyć dwa puste pliki przy użyciu tej samej konstrukcji, którą podałeś?
Tasdik Rahman
Czy istnieje sposób, aby utworzyć katalog nadrzędny, jeśli nie istnieje, czy też muszę to zrobić osobno?
falsePockets
Musisz upewnić się, że katalog nadrzędny istnieje i umożliwia zapis. Zobacz stackoverflow.com/questions/22844905/…
René Pijl
37

Coś takiego (użycie statmodułu najpierw do zebrania danych o nim, a następnie filtrowanie za pomocą warunku) powinno działać:

- 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

Alternatywnie możesz wykorzystać tę changed_whenfunkcjonalność.

ceejayoz
źródło
20
może powinno być: "when: not p.stat.exists"
piro
28

Inna opcja, korzystając z modułu poleceń:

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

Argument „tworzy” zapewnia, że ​​ta akcja nie zostanie wykonana, jeśli plik istnieje.

Leynos
źródło
5
Należy unikać poleceń tak bardzo, jak to możliwe, ponieważ nie jest to idempotentne. ryaneschinger.com/blog/…
redshark1802
4
@ redshark1802 Zgoda. Chociaż w tym przypadku zadanie jest idempotentne, ponieważ nie zostanie wykonane, jeśli „/ ścieżka / do / pliku” już istnieje. Myślę, że rozwiązanie René Pijl jest bardziej podobne do Ansible z trzech najpopularniejszych odpowiedzi i zdecydowanie tym, którego powinieneś użyć, jeśli chcesz ustawić własność, tryb itp.
Leynos
15

Opierając się na zaakceptowanej odpowiedzi, jeśli chcesz, aby plik był sprawdzany pod kątem uprawnień przy każdym uruchomieniu, a te zmieniły się odpowiednio, jeśli plik istnieje, lub po prostu utwórz plik, jeśli nie istnieje, możesz użyć następującego:

- 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
źródło
3
Ta odpowiedź jest niesamowita ze względu na elastyczność, jaką daje w definiowaniu atrybutów pliku, jeśli nie istnieje.
Dejay Clayton
10

file: path=/etc/nologin state=touch

Pełny odpowiednik dotyku (nowość w 1.4+) - użyj stat, jeśli nie chcesz zmieniać znacznika czasu pliku.

jalmasi
źródło
3
To nie jest idempotentne, data pliku zostanie zmodyfikowana po wykonaniu eacheracji playbooka ansibla.
Jérôme B
3
@ Jérôme B Nowość w Ansible 2.7: możesz sprawić, że będzie to idempotentne file: path=/etc/nologin state=touch modification_time=preserve access_time=preserve.
GregV
8

moduł plików zapewnia sposób na dotknięcie pliku bez modyfikowania jego czasu.

- 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

Źródła: https://docs.ansible.com/ansible/latest/modules/file_module.html

Ravi Kulkarni
źródło
To jest prawidłowa odpowiedź dla ansibla 2.7+, jednak brakuje w nim ważnych informacji.
Honza,
3

Okazuje się, że nie mam wystarczającej reputacji, aby zamieścić to jako komentarz, co byłoby bardziej odpowiednim miejscem do tego:

Re. Odpowiedź AllBlackta, jeśli wolisz format wielowierszowy Ansible, musisz dostosować cytowanie state(spędziłem kilka minut na pracy nad tym, więc mam nadzieję, że przyspieszy to kogoś innego),

- 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
źródło
0

Aby utworzyć plik na zdalnym komputerze za pomocą polecenia ad-hoc

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

Proszę, popraw mnie jeśli się mylę

vajrala chakradhar reddy
źródło
0

Zmienione, jeśli plik nie istnieje. Utwórz pusty plik.

- name: create fake 'nologin' shell
  file:
    path: /etc/nologin
    state: touch
  register: p
  changed_when: p.diff.before.state == "absent"
Dmitry Balashov
źródło
0

Połączenie dwóch odpowiedzi z niespodzianką. Kod zostanie wykryty jako zmieniony po utworzeniu pliku lub zaktualizowaniu uprawnień.

- 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"

oraz wersję, która również poprawia właściciela i grupę oraz wykrywa je jako zmienione, gdy koryguje te:

- 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
źródło
Tylko ansibl 2.7+ - to należy wspomnieć.
Honza,