Ansible: Wie lösche ich Dateien und Ordner in einem Verzeichnis?


152

Der folgende Code löscht nur die erste Datei, die er im Webverzeichnis erhält. Ich möchte alle Dateien und Ordner im Webverzeichnis entfernen und das Webverzeichnis beibehalten. Wie kann ich das machen?

  - name: remove web dir contents
     file: path='/home/mydata/web/{{ item }}' state=absent
     with_fileglob:
       - /home/mydata/web/*

Hinweis: Ich habe versucht rm -rf, Befehl und Shell zu verwenden, aber sie funktionieren nicht. Vielleicht benutze ich sie falsch.

Jede Hilfe in die richtige Richtung wird geschätzt.

Ich benutze ansible 2.1.0.0


Sieht aus wie ein Käfer.
Ceving

Antworten:


134

Der folgende Code löscht den gesamten Inhalt von artifact_path

- name: Clean artifact path
  file:
    state: absent
    path: "{{ artifact_path }}/"

Hinweis : Dadurch wird auch das Verzeichnis gelöscht.


3
Anführungszeichen sind nicht erforderlich. Dies ist nur mein Arbeitscode. Artefaktpfad ist wie / app / my_app / work /
Mohan Kumar P

83
Das OP (und ich) wollen eine Lösung, die den Inhalt des Ordners löscht, ABER NICHT den Ordner selbst. Diese Lösung löscht den Inhalt UND den Ordner selbst.
stochastisch

19
Wie kam es zu einer positiven Abstimmung? Dadurch wird auch das Verzeichnis gelöscht.
Deppfx

17
Hat jemand den obigen Code mit Artefakt_Pfad null fehlgeschlagen? Dies rm -rf /
scheint

2
@ Ted-K42 Ich würde so etwas tun, nur um sicher zu gehen:when: artifact_path is defined and artifact_path != ""
Bmaupin

69

Shell-Modul verwenden (auch idempotent ):

- shell: /bin/rm -rf /home/mydata/web/*

Sauberste Lösung, wenn Sie sich nicht um das Erstellungsdatum und den Eigentümer / die Berechtigungen kümmern:

- file: path=/home/mydata/web state=absent
- file: path=/home/mydata/web state=directory

7
Funktioniert, entfernt jedoch keine Dateien, die mit beginnen. wie .htaccess
Abbas

Shell hat auch für mich gearbeitet. Exakt gleiche Aufgabe , aber tauschte shellin für commandund es funktioniert
SomethingOn

4
Platzhalter funktionieren nicht mit
Befehlen,

1
Beachten Sie, dass dies Ihre Berechtigungen / Eigentümer ändern kann, sofern Sie dies nicht explizit während des Erstellungszeitpunkts festlegen.
NeverEndingQueue

Wenn Sie die Shell verwenden, erhalten Sie eine Warnung, dass Sie das Dateimodul mit state = abwesend anstelle von shell rm verwenden. Um dies zu vermeiden, fügen Sie einfach Argumente hinzu: warn: false
Rodrigo

59

Entfernen Sie das Verzeichnis (im Grunde eine Kopie von https://stackoverflow.com/a/38201611/1695680 ). Ansible führt diesen Vorgang rmtreeunter der Haube aus.

- name: remove files and directories
  file:
    state: "{{ item }}"
    path: "/srv/deleteme/"
    owner: 1000  # set your owner, group, and mode accordingly
    group: 1000
    mode: '0777'
  with_items:
    - absent
    - directory

Wenn Sie nicht den Luxus haben, das gesamte Verzeichnis zu entfernen und neu zu erstellen, können Sie es nach Dateien (und Verzeichnissen) durchsuchen und nacheinander löschen. Welches wird eine Weile dauern. Sie möchten wahrscheinlich sicherstellen, dass Sie [ssh_connection]\npipelining = Truein Ihrer ansible.cfg auf haben.

- block:
  - name: 'collect files'
    find:
      paths: "/srv/deleteme/"
      hidden: True
      recurse: True
      # file_type: any  # Added in ansible 2.3
    register: collected_files

  - name: 'collect directories'
    find:
      paths: "/srv/deleteme/"
      hidden: True
      recurse: True
      file_type: directory
    register: collected_directories

  - name: remove collected files and directories
    file:
      path: "{{ item.path }}"
      state: absent
    with_items: >
      {{
        collected_files.files
        + collected_directories.files
      }}

5
Die erste Aufgabe ist die eleganteste Lösung, die ich je gesehen habe. Beachten Sie die Kommentare an anderer Stelle, dass eine lang laufende Feature-Anfrage hinzugefügt werden mussstate=empty
William Turrell

24

Die rm-Lösung hat mir wirklich nicht gefallen, auch ansible gibt Ihnen Warnungen vor der Verwendung von rm. Hier erfahren Sie, wie Sie dies ohne die Notwendigkeit von rm und ohne ansible Warnungen tun können.

- hosts: all
  tasks:
  - name: Ansible delete file glob
    find:
      paths: /etc/Ansible
      patterns: "*.txt"
    register: files_to_delete

  - name: Ansible remove file glob
    file:
      path: "{{ item.path }}"
      state: absent
    with_items: "{{ files_to_delete.files }}"

Quelle: http://www.mydailytutorials.com/ansible-delete-multiple-files-directories-ansible/


doch die beste lösung für die frage !!
Vsegar

18

Versuchen Sie den folgenden Befehl, es sollte funktionieren

- shell: ls -1 /some/dir
  register: contents

- file: path=/some/dir/{{ item }} state=absent
  with_items: {{ contents.stdout_lines }}

3
Sie haben es versäumt, die letzte Zeile mit {{,}} korrekt zu verlassen, umwith_items: "{{ contents.stdout_lines }}"
Valerio Crini

Es ist gefährlich, die lsAusgabe zu verwenden, um Dateinamen abzurufen, da Dateinamen mit Sonderzeichen wie Zeilenumbrüchen nicht korrekt gedruckt werden.
Bfontaine

5

Aus allen Kommentaren und Vorschlägen wurde eine insgesamt überarbeitete und ausfallsichere Implementierung erstellt:

# collect stats about the dir
- name: check directory exists
  stat:
    path: '{{ directory_path }}'
  register: dir_to_delete

# delete directory if condition is true
- name: purge {{directory_path}}
  file:
    state: absent
    path: '{{ directory_path  }}'
  when: dir_to_delete.stat.exists and dir_to_delete.stat.isdir

# create directory if deleted (or if it didn't exist at all)
- name: create directory again
  file:
    state: directory
    path: '{{ directory_path }}'
  when: dir_to_delete is defined or dir_to_delete.stat.exist == False

Ich denke du vermisst das registerfür plugin_dir_deleted, oder?
Bob Vork

Vielen Dank für den Hinweis. Ich habe diesen Code aus einem meiner Playbooks herausnehmen lassen und ihn in Bezug auf die Benennung allgemeiner gestaltet, aber vergessen, zwei Variablennamen zu ersetzen
Markus

1
Gutes Zeug, aber ich denke, der Status in der letzten Aufgabe muss auf "Verzeichnis" anstatt auf "Vorhanden" gesetzt werden.
Andrew Allaire

1
Sie sollten Ihr stat-Ergebnis verwenden, um die Berechtigungen beizubehalten: Eigentümer von pw_name, Gruppe von gr_name und Modus von Modus.
DylanYoung

versucht, owner: dir_to_delete.stat.pw_name, group: dir_to_delete.stat.gr_name mode: dir_to_delete.stat.modeaber es schlägt bei mir mit meiner aktuellen Ansible-Version fehl :(
Markus

3

Mit File Glob wird es auch funktionieren. Der von Ihnen veröffentlichte Code enthält einen Syntaxfehler. Ich habe geändert und getestet, dass dies funktionieren sollte.

- name: remove web dir contents
  file:
    path: "{{ item }}"
    state: absent
  with_fileglob:
    - "/home/mydata/web/*"

7
with_fileglobfunktioniert nur auf einem lokalen Computer, nicht auf einem Remote-Computer. ist es nicht wahr?
Stepan Vavra

True .. with_fileglob ist nur für Einheimische
Deepali Mittal

Außerdem werden dadurch keine Verzeichnisse gelöscht, sondern nur Dateien gelöscht.
Vikas027

2

Während Ansible noch über die Implementierung von https://github.com/ansible/ansible-modules-core/issues/902 debattiertstate = empty

my_folder: "/home/mydata/web/"
empty_path: "/tmp/empty"


- name: "Create empty folder for wiping."
  file:
    path: "{{ empty_path }}" 
    state: directory

- name: "Wipe clean {{ my_folder }} with empty folder hack."
  synchronize:
    mode: push

    #note the backslash here
    src: "{{ empty_path }}/" 

    dest: "{{ nl_code_path }}"
    recursive: yes
    delete: yes
  delegate_to: "{{ inventory_hostname }}"

Beachten Sie jedoch, dass Sie mit "Synchronisieren" Ihre Dateien (mit "Löschen") trotzdem ordnungsgemäß synchronisieren können sollten.


2

Das habe ich mir ausgedacht:

- name: Get directory listing
  find:
    path: "{{ directory }}" 
    file_type: any
    hidden: yes
  register: directory_content_result

- name: Remove directory content
  file:
    path: "{{ item.path }}" 
    state: absent
  with_items: "{{ directory_content_result.files }}" 
  loop_control:
    label: "{{ item.path }}" 

Zuerst erhalten wir eine Verzeichnisliste mit der findEinstellung

  • file_typezu anyso würden wir nicht verpassen verschachtelte Verzeichnisse und Links,
  • hiddenzu yes, damit wir keine versteckten Dateien überspringen
  • Setzen Sie auch nicht recurseauf yes, da dies nicht nur unnötig ist, sondern auch die Ausführungszeit verlängern kann.

Dann gehen wir diese Liste mit fileModul durch. Die Ausgabe ist etwas ausführlich und loop_control.labelhilft uns daher bei der Begrenzung der Ausgabe (ich habe diesen Rat gefunden hier ).


Aber ich fand die vorherige Lösung etwas langsam, da sie den Inhalt durchläuft, also ging ich mit:

- name: Get directory stats
  stat:
    path: "{{ directory }}"
  register: directory_stat

- name: Delete directory
  file:
    path: "{{ directory }}"
    state: absent

- name: Create directory
  file:
    path: "{{ directory }}"
    state: directory
    owner: "{{ directory_stat.stat.pw_name }}"
    group: "{{ directory_stat.stat.gr_name }}"
    mode: "{{ directory_stat.stat.mode }}"
  • Holen Sie sich Verzeichnis-Eigenschaften mit dem stat
  • Verzeichnis löschen
  • Verzeichnis mit denselben Eigenschaften neu erstellen.

Das hat mir gereicht, aber Sie können auch hinzufügen attributes, wenn Sie wollen.


1

Es ist ein Problem offenDiesbezüglich .

Im Moment funktioniert die Lösung für mich: Erstellen Sie lokal einen leeren Ordner und synchronisieren Sie ihn mit dem Remote-Ordner.

Hier ist ein Beispiel für ein Spielbuch:

- name: "Empty directory"
  hosts: *
  tasks:
    - name: "Create an empty directory (locally)"
      local_action:
        module: file
        state: directory
        path: "/tmp/empty"

    - name: Empty remote directory
      synchronize:
        src: /tmp/empty/
        dest: /home/mydata/web/
        delete: yes
        recursive: yes

1

Ich habe ein benutzerdefiniertes ansible-Modul zum Bereinigen von Dateien geschrieben, das auf mehreren Filtern wie Alter, Zeitstempel, Glob-Mustern usw. basiert.

Es ist auch kompatibel mit ansible älteren Versionen. Es kann hier gefunden werden .

Hier ist ein Beispiel:

- cleanup_files:
  path_pattern: /tmp/*.log
  state: absent
  excludes:
    - foo*
    - bar*

0

Ich möchte sicherstellen, dass der Befehl find nur alles im Verzeichnis löscht und das Verzeichnis intakt lässt, da das Verzeichnis in meinem Fall ein Dateisystem ist. Das System generiert beim Versuch, ein Dateisystem zu löschen, einen Fehler, aber das ist keine gute Option. Ich verwende die Shell-Option, da dies die einzige funktionierende Option ist, die ich bisher für diese Frage gefunden habe.

Was ich getan habe:

Bearbeiten Sie die Hosts-Datei, um einige Variablen einzugeben:

[all:vars]
COGNOS_HOME=/tmp/cognos
find=/bin/find

Und erstelle ein Spielbuch:

- hosts: all
  tasks:
  - name: Ansible remove files
    shell: "{{ find }} {{ COGNOS_HOME }} -xdev -mindepth 1 -delete"

Dadurch werden alle Dateien und Verzeichnisse im Variablenverzeichnis / Dateisystem COGNOS_HOME gelöscht. Die Option "-mindepth 1" stellt sicher, dass das aktuelle Verzeichnis nicht berührt wird.


0

Nur eine kleine sauberere Copy & Paste-Vorlage von ThorSummoners Antwort, wenn Sie Ansible> = 2.3 verwenden (Unterscheidung zwischen Dateien und Verzeichnissen nicht mehr erforderlich.)

- name: Collect all fs items inside dir
  find:
    path: "{{ target_directory_path }}"
    hidden: true
    file_type: any
  changed_when: false
  register: collected_fsitems
- name: Remove all fs items inside dir
  file:
    path: "{{ item.path }}"
    state: absent
  with_items: "{{ collected_fsitems.files }}"
  when: collected_fsitems.matched|int != 0

-1

Angenommen, Sie sind immer unter Linux, versuchen Sie es mit dem findcmd.

- name: Clean everything inside {{ item }}
  shell: test -d {{ item }} && find {{ item }} -path '{{ item }}/*' -prune -exec rm -rf {} \;
  with_items: [/home/mydata/web]

Dies sollte Dateien / Ordner / versteckt unter löschen /home/mydata/web


1
Es mag funktionieren, aber die Verwendung des Shell-Moduls sollte immer das letzte Mittel sein.
Chris

-1
先 删除 对应 的 目录 , 然后 在 创建 该 目录 , , 使用 的 是 嵌套 循环
  - name: delete old data and clean cache
    file:
      path: "{{ item[0] }}" 
      state: "{{ item[1] }}"
    with_nested:
      - [ "/data/server/{{ app_name }}/webapps/", "/data/server/{{ app_name }}/work/" ]
      - [ "absent", "directory" ]
    ignore_errors: yes

-4

Das ist mein Beispiel.

  1. Repo installieren
  2. Installieren Sie das rsyslog-Paket
  3. rsyslog stoppen
  4. Löschen Sie alle Dateien in / var / log / rsyslog /
  5. Starten Sie rsyslog

    - hosts: all
      tasks:
        - name: Install rsyslog-v8 yum repo
          template:
            src: files/rsyslog.repo
            dest: /etc/yum.repos.d/rsyslog.repo
    
        - name: Install rsyslog-v8 package
          yum:
            name: rsyslog
            state: latest
    
        - name: Stop rsyslog
          systemd:
            name: rsyslog
            state: stopped
    
        - name: cleann up /var/spool/rsyslog
          shell: /bin/rm -rf /var/spool/rsyslog/*
    
        - name: Start rsyslog
          systemd:
            name: rsyslog
            state: started
    

-6

Unten hat für mich gearbeitet,

- name: Ansible delete html directory
  file:
   path: /var/www/html
   state: directory

Dies bestätigt nur, dass das Verzeichnis existiert. Es wird erstellt, wenn dies nicht der Fall ist. Wenn dies der Fall ist, wird nur OK gemeldet.
Chris
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.