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.