Ansible: come eliminare file e cartelle all'interno di una directory?


152

Il codice seguente elimina solo il primo file che ottiene all'interno della directory web. Voglio rimuovere tutti i file e le cartelle all'interno della directory web e conservare la directory web. Come lo posso fare?

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

Nota: ho provato a rm -rfusare command e shell, ma non funzionano. Forse li sto usando erroneamente.

Qualsiasi aiuto nella giusta direzione sarà apprezzato.

Sto usando ansible 2.1.0.0


Sembra un insetto.
— ceving il

Risposte:


132

Di seguito il codice eliminerà l'intero contenuto di artifact_path

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

Nota : questo cancellerà anche la directory.


3
le quotazioni non sono richieste. Questo è solo il mio codice di lavoro. artifact_path è come / app / my_app / work /
— Mohan Kumar P

83
L'OP (e me stesso) desidera una soluzione che eliminerà il contenuto della cartella MA NON la cartella stessa. Questa soluzione elimina il contenuto E la cartella stessa.
— stocastico

19
Come è potuto ottenere un voto? Questo elimina anche la directory.
— deppfx,

17
Qualcuno ha avuto il codice sopra fallito su di loro con artefact_path essendo null? Sembra che potrebbe essere suscettibile a uno di quei grandi rm -rf /momenti della storia
— ted-k42,

2
@ ted-k42 Farei una cosa del genere solo per sicurezza:when: artifact_path is defined and artifact_path != ""
— bmaupin,

69

Utilizzando il modulo shell ( anche idempotente ):

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

Soluzione più pulita se non ti interessano la data di creazione e il proprietario / autorizzazioni:

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

7
Funziona ma non ha rimosso i file che iniziano con. come .htaccess
— Abbas,

Shell ha lavorato anche per me. Esattamente lo stesso compito, ma scambiato shella commande funziona
— SomethingOn

4
I caratteri jolly non funzionano con il comando poiché richiedono una shell per l'espansione
— JamesP,

1
Si noti che ciò potrebbe modificare le autorizzazioni / il proprietario a meno che non venga impostato esplicitamente durante il momento della creazione.
— NeverEndingQueue

Usando la shell riceverai un avviso sull'uso del modulo file con state = assente invece della shell rm. Per evitarlo basta aggiungere args: warn: false
— Rodrigo

60

Rimuovere la directory (fondamentalmente una copia di https://stackoverflow.com/a/38201611/1695680 ), Ansible esegue questa operazione rmtreesotto il cofano.

- 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

Se non hai il lusso di rimuovere l'intera directory e ricrearla, puoi scansionarla alla ricerca di file (e directory) ed eliminarli uno per uno. Il che richiederà del tempo. Probabilmente vuoi assicurarti di avere [ssh_connection]\npipelining = Truenel tuo ansible.cfg attivo.

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

6
Il primo compito è la soluzione più elegante che abbia mai visto. Nota altrove che c'è una richiesta di funzionalità di lunga data da aggiungerestate=empty
— William Turrell,

24

Non mi è davvero piaciuta la soluzione rm, anche ansible ti dà avvertimenti sull'uso di rm. Quindi, ecco come farlo senza la necessità di rm e senza avvisi di risposta.

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

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


eppure la migliore soluzione per la domanda !!
— Vsegar

18

prova il comando seguente, dovrebbe funzionare

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

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

3
hai mancato di sfuggire correttamente all'ultima riga con {{,}} per ottenerewith_items: "{{ contents.stdout_lines }}"
— Valerio Crini il

È pericoloso usare lsl'output di '' per ottenere i nomi dei file perché non stampa correttamente i nomi dei file con caratteri speciali come newline.
— bfontaine,

5

Creato un'implementazione generale revisionata e senza errori da tutti i commenti e suggerimenti:

# 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

Penso che ti manchi il registerper plugin_dir_deleted, giusto?
— Bob Vork,

grazie per averlo segnalato. Ho preso questo pezzo di codice da uno dei miei playbook e l'ho reso più generico in termini di denominazione, ma ho dimenticato di sostituire due nomi di variabili
— Markus,

1
Roba buona, ma penso che lo stato dell'ultima attività debba essere impostato su "directory" anziché "presente".
— Andrew Allaire,

1
È necessario utilizzare il risultato stat per conservare le autorizzazioni: proprietario da pw_name, gruppo da gr_name e mode da mode.
— DylanYoung,

provato owner: dir_to_delete.stat.pw_name, group: dir_to_delete.stat.gr_name mode: dir_to_delete.stat.modema non ci riesce con la mia attuale versione di Ansible :(
— Markus

3

Usando anche il file glob funzionerà. Si è verificato un errore di sintassi nel codice che hai pubblicato. Ho modificato e testato questo dovrebbe funzionare.

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

7
with_fileglobfunziona solo su macchine locali, non remote; non è vero?
— Stepan Vavra,

Vero .. with_fileglob è solo per locali
— Deepali Mittal,

Inoltre, questo non elimina le directory, solo i file vengono eliminati.
— vikas027,

2

Mentre Ansible sta ancora discutendo di implementare state = empty https://github.com/ansible/ansible-modules-core/issues/902

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

Nota però, con la sincronizzazione dovresti essere in grado di sincronizzare i tuoi file (con eliminazione) in modo corretto comunque.


2

Ecco cosa mi viene in mente:

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

In primo luogo, stiamo ottenendo l'elenco delle directory con find, impostazione

  • file_typea any, quindi non ci perderemmo le directory e i link nidificati
  • hiddena yes, quindi non saltiamo i file nascosti
  • inoltre, non impostare recursesu yes, poiché non è solo non necessario, ma può aumentare i tempi di esecuzione.

Quindi, passiamo attraverso l'elenco con il filemodulo. L'output è un po 'dettagliato, quindi loop_control.labelci aiuterà a limitare l'output (puoi trovare questo consiglio qui ).


Ma ho trovato la soluzione precedente un po 'lenta, poiché scorre il contenuto, quindi sono andato con:

- 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 }}"
  • ottenere le proprietà della directory con il stat
  • cancella directory
  • ricreare la directory con le stesse proprietà.

Questo è stato abbastanza per me, ma puoi anche aggiungere attributes, se vuoi.


1

C'è un problema aperto al riguardo.

Per ora, la soluzione funziona per me: crea una cartella vuota localmente e sincronizzala con quella remota.

Ecco un playbook di esempio:

- 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

Ho scritto un modulo Ansible personalizzato per ripulire i file in base a più filtri come età, timestamp, modelli glob, ecc.

È anche compatibile con le versioni precedenti rispondibili. Esso può essere trovato qui .

Ecco un esempio:

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

0

Voglio assicurarmi che il comando find cancelli solo tutto all'interno della directory e lasci intatta la directory perché nel mio caso la directory è un filesystem. Il sistema genererà un errore quando si tenta di eliminare un filesystem ma questa non è una buona opzione. Sto usando l'opzione shell perché questa è l'unica opzione funzionante che ho trovato finora per questa domanda.

Cosa ho fatto:

Modifica il file hosts per inserire alcune variabili:

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

E crea un playbook:

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

Ciò eliminerà tutti i file e le directory nella directory / filesystem delle variabili COGNOS_HOME. L'opzione "-mindepth 1" assicura che la directory corrente non verrà toccata.


0

Basta un piccolo modello più pulito di copia e incolla della risposta di ThorSummoners, se stai usando Ansible> = 2.3 (la distinzione tra file e dir non è più necessaria.)

- 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

Supponendo che tu sia sempre in Linux, prova il findcmd.

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

Questo dovrebbe cancellare i file / cartelle / nascosto sotto /home/mydata/web


1
Potrebbe funzionare ma l'utilizzo del modulo shell dovrebbe essere sempre l'ultima risorsa.
— 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

Questo è il mio esempio

  1. Installa repository
  2. Installa il pacchetto rsyslog
  3. ferma rsyslog
  4. elimina tutti i file all'interno di / var / log / rsyslog /
  5. avvia 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

Di seguito ha funzionato per me,

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

Ciò confermerà solo che la directory esiste. Lo creerà se non lo fa ma non fa altro che segnalare OK se lo fa.
— Chris,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.