Wie erstelle ich eine leere Datei mit Ansible?

115

Was ist der einfachste Weg, um eine leere Datei mit Ansible zu erstellen? Ich weiß, dass ich eine leere Datei im filesVerzeichnis speichern und dann auf den Remote-Host kopieren kann, aber ich finde das etwas unbefriedigend.

Eine andere Möglichkeit besteht darin, eine Datei auf dem Remote-Host zu berühren:

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

Aber dann wird die Datei jedes Mal berührt und als gelbe Linie im Protokoll angezeigt, was ebenfalls unbefriedigend ist ...

Gibt es eine bessere Lösung für dieses einfache Problem?

dokaspar
quelle

Antworten:

189

In der Dokumentation des Dateimoduls heißt es

Wenn state=filedie Datei NICHT erstellt wird, wenn sie nicht vorhanden ist, lesen Sie das Kopier- oder Vorlagenmodul, wenn Sie dieses Verhalten wünschen.

Daher verwenden wir das Kopiermodul, force=noum eine neue leere Datei nur dann zu erstellen, wenn die Datei noch nicht vorhanden ist (wenn die Datei vorhanden ist, bleibt ihr Inhalt erhalten).

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

Dies ist eine deklarative und elegante Lösung.

René Pijl
quelle
15
@ ÁkosVandra: Eigentlich nicht. Siehe : force: no.
Palacsint
Danke - dies ist eine viel schönere Lösung als file / touch oder die akzeptierte stat / file-Antwort und ist einfach mit "with_items"
Realist
Gute Antwort, war neugierig, wie man zwei leere Dateien mit demselben Konstrukt erstellen würde, das Sie bereitgestellt haben?
Tasdik Rahman
Gibt es eine Möglichkeit, das übergeordnete Verzeichnis zu erstellen, wenn es nicht vorhanden ist, oder muss ich das separat tun?
falsePockets
Sie müssen sicherstellen, dass das übergeordnete Verzeichnis vorhanden und beschreibbar ist. Siehe stackoverflow.com/questions/22844905/…
René Pijl
37

So etwas (das statModul zuerst verwenden, um Daten darüber zu sammeln und dann mit einer Bedingung zu filtern) sollte funktionieren:

- 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

Alternativ können Sie möglicherweise die changed_whenFunktionalität nutzen.

ceejayoz
quelle
20
Vielleicht sollte es sein: "Wann: nicht p.stat.exists"
Piro
28

Eine weitere Option, die das Befehlsmodul verwendet:

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

Das Argument 'create' stellt sicher, dass diese Aktion nicht ausgeführt wird, wenn die Datei vorhanden ist.

Leynos
quelle
5
Sie sollten Befehle so weit wie möglich vermeiden, da sie nicht idempotent sind. ryaneschinger.com/blog/…
redshark1802
4
@ redshark1802 Einverstanden. Obwohl in diesem Fall die Aufgabe idempotent ist, wird sie nicht ausgeführt, wenn "/ path / to / file" bereits vorhanden ist. Ich denke, René Pijls Lösung ist die Ansible-ähnliche der drei Top-Antworten und definitiv die, die Sie verwenden sollten, wenn Sie Eigentümer, Modus usw.
festlegen müssen
15

Aufbauend auf der akzeptierten Antwort können Sie Folgendes verwenden, wenn Sie möchten, dass die Datei bei jedem Lauf auf Berechtigungen überprüft wird und diese entsprechend geändert werden, wenn die Datei vorhanden ist, oder wenn Sie die Datei nur erstellen, wenn sie nicht vorhanden ist:

- 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
quelle
3
Diese Antwort ist fantastisch, da Sie die Dateiattribute einer Datei flexibel definieren können, wenn sie nicht vorhanden ist.
Dejay Clayton
10

file: path=/etc/nologin state=touch

Volles Äquivalent zu Touch (neu in 1.4+) - Verwenden Sie stat, wenn Sie den Zeitstempel der Datei nicht ändern möchten.

Jalmasi
quelle
3
Es ist nicht idempotent, das Dateidatum wird bei jeder Ausführung des ansible Playbooks geändert.
Jérôme B
3
@ Jérôme B Neu in Ansible 2.7: Sie können es idempotent machen mit file: path=/etc/nologin state=touch modification_time=preserve access_time=preserve.
GregV
8

Das Dateimodul bietet die Möglichkeit, Dateien zu berühren, ohne ihre Zeit zu ändern.

- 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

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

Ravi Kulkarni
quelle
Dies ist die richtige Antwort für ansible 2.7+, jedoch fehlen wichtige Informationen.
Honza
3

Es stellt sich heraus, dass ich nicht genug Ruf habe, um dies als Kommentar zu formulieren, was ein geeigneterer Ort dafür wäre:

Re. AllBlackt's Antwort: Wenn Sie das mehrzeilige Format von Ansible bevorzugen, müssen Sie das Angebot anpassen state(ich habe ein paar Minuten damit verbracht, dies auszuarbeiten, also hoffentlich beschleunigt dies jemand anderen).

- 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
quelle
0

Um mit dem Ad-hoc-Befehl eine Datei auf dem Remotecomputer zu erstellen

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

Bitte korrigieren Sie mich, wenn ich falsch liege

Vajrala Chakradhar Reddy
quelle
0

Geändert, wenn Datei nicht vorhanden ist. Leere Datei erstellen.

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

Eine Kombination aus zwei Antworten mit einer Wendung. Der Code wird als geändert erkannt, wenn die Datei erstellt oder die Berechtigung aktualisiert wird.

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

und eine Version, die auch den Eigentümer und die Gruppe korrigiert und als geändert erkennt, wenn diese korrigiert werden:

- 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
quelle
nur ansible 2.7+ - das sollte erwähnt werden.
Honza