Ansible: ¿Cómo eliminar archivos y carpetas dentro de un directorio?


152

El siguiente código solo elimina el primer archivo que se encuentra dentro del directorio web. Quiero eliminar todos los archivos y carpetas dentro del directorio web y conservar el directorio web. ¿Cómo puedo hacer eso?

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

Nota: He intentado rm -rfusar el comando y el shell, pero no funcionan. Quizás los estoy usando mal.

Cualquier ayuda en la dirección correcta será apreciada.

Estoy usando ansible 2.1.0.0


Parece un error
ceving

Respuestas:


132

El siguiente código eliminará todo el contenido de artifact_path

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

Nota : esto también eliminará el directorio.


3
No se requieren cotizaciones. Este es solo mi código de trabajo. artifact_path es como / app / my_app / work /
Mohan Kumar P

83
El OP (y yo) queremos una solución que elimine el contenido de la carpeta PERO NO la carpeta en sí. Esta solución elimina el contenido Y la carpeta en sí.
estocástico

19
¿Cómo obtuvo esto un voto a favor? Esto también elimina el directorio.
deppfx

17
¿Alguien ha fallado en el código anterior con artifact_path siendo nulo? rm -rf /
Parece

2
@ ted-k42 Haría algo como esto solo para estar seguro:when: artifact_path is defined and artifact_path != ""
bmaupin

69

Usando el módulo de shell ( también idempotente ):

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

Solución más limpia si no le importa la fecha de creación y el propietario / permisos:

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

77
Funciona pero no eliminó los archivos a partir de. como .htaccess
Abbas

Shell también trabajó para mí. Misma tarea exacta, pero cambió shellpor commandy funciona
SomethingOn

44
Los comodines no funcionarán con el comando, ya que requieren un shell para la expansión
JamesP

1
Tenga en cuenta que esto podría cambiar sus permisos / propietario a menos que establezca explícitamente durante el momento de creación.
NeverEndingQueue

Al usar shell , recibirá una advertencia sobre el uso del módulo de archivo con state = ausente en lugar de shell rm. Para evitarlo, simplemente agregue args: warn: false
Rodrigo

60

Elimine el directorio (básicamente una copia de https://stackoverflow.com/a/38201611/1695680 ), Ansible realiza esta operación rmtreebajo el capó.

- 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

Si no tiene el lujo de eliminar todo el directorio y volver a crearlo, puede escanearlo en busca de archivos (y directorios) y eliminarlos uno por uno. Lo que llevará un tiempo. Probablemente quiera asegurarse de tener [ssh_connection]\npipelining = Trueen su ansible.cfg encendido.

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

66
La primera tarea es la solución más elegante que he visto. Tenga en cuenta los comentarios en otra parte que hay una solicitud de función de larga duración para agregarstate=empty
William Turrell

24

Realmente no me gustó la solución rm, también ansible te da advertencias sobre el uso de rm. Así que aquí es cómo hacerlo sin la necesidad de rm y sin advertencias ansibles.

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

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


¡Sin embargo, la mejor solución para la pregunta!
Vsegar

18

prueba el siguiente comando, debería funcionar

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

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

3
te perdiste para escapar correctamente la última línea con {{,}} para obtenerwith_items: "{{ contents.stdout_lines }}"
Valerio Crini

Es peligroso usar ls'output para obtener nombres de archivos porque no imprime correctamente nombres de archivos con caracteres especiales como líneas nuevas.
bfontaine

5

Creé una implementación general revisada y segura de todos los comentarios y sugerencias:

# 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

Creo que te estás perdiendo el registerpara plugin_dir_deleted, ¿verdad?
Bob Vork

Gracias por señalar esto. Tomé este código de uno de mis libros de jugadas y lo hice más genérico en términos de nomenclatura, pero olvidé reemplazar dos nombres de variables
Markus el

1
Cosas buenas, pero creo que el estado en la última tarea debe establecerse en "directorio" en lugar de "presente".
Andrew Allaire

1
Debe usar el resultado de su estadística para conservar los permisos: propietario de pw_name, grupo de gr_name y modo de modo.
DylanYoung

intentado owner: dir_to_delete.stat.pw_name, group: dir_to_delete.stat.gr_name mode: dir_to_delete.stat.modepero me falla con mi versión actual de Ansible :(
Markus

3

Usando file glob también funcionará. Hay algún error de sintaxis en el código que publicó. He modificado y probado esto debería funcionar.

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

77
with_fileglobfunciona solo en máquinas locales, no remotas; no es verdad?
Stepan Vavra

Es cierto .. with_fileglob es solo para locales
Deepali Mittal

Además, esto no elimina directorios, solo se eliminan los archivos.
vikas027

2

Si bien Ansible aún está debatiendo implementar 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 }}"

Sin embargo, tenga en cuenta que, con la sincronización, debería poder sincronizar sus archivos (con eliminar) de todos modos.


2

Eso es lo que se me ocurre:

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

Primero, estamos obteniendo una lista de directorios con find, estableciendo

  • file_typea any, para que no nos perdamos los directorios y enlaces anidados
  • hiddena yes, para no omitir archivos ocultos
  • También, no se ajusta recursea yes, ya que no sólo es innecesario, pero puede aumentar el tiempo de ejecución.

Luego, revisamos esa lista con el filemódulo. Su salida es un poco detallada, por loop_control.labello que nos ayudará a limitar la salida (encontré este consejo aquí ).


Pero encontré que la solución anterior era algo lenta, ya que itera a través del contenido, así que seguí 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 }}"
  • obtener propiedades de directorio con el stat
  • eliminar directorio
  • recrear directorio con las mismas propiedades.

Eso fue suficiente para mí, pero también puede agregar attributes, si lo desea.


1

Hay un problema abierto con respecto a esto.

Por ahora, la solución funciona para mí: crear una carpeta vacía localmente y sincronizarla con la remota.

Aquí hay un libro de jugadas de muestra:

- 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

He escrito un módulo ansible personalizado para limpiar archivos basado en múltiples filtros como antigüedad, marca de tiempo, patrones globales, etc.

También es compatible con versiones anteriores ansibles. Se puede encontrar aquí .

Aquí hay un ejemplo:

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

0

Quiero asegurarme de que el comando find solo elimine todo dentro del directorio y deje el directorio intacto porque en mi caso el directorio es un sistema de archivos. El sistema generará un error al intentar eliminar un sistema de archivos, pero esa no es una buena opción. Estoy usando la opción de shell porque esa es la única opción de trabajo que encontré hasta ahora para esta pregunta.

Lo que hice:

Edite el archivo de hosts para incluir algunas variables:

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

Y crea un libro de jugadas:

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

Esto eliminará todos los archivos y directorios en el directorio / sistema de archivos variable COGNOS_HOME. La opción "-mindepth 1" asegura que no se toque el directorio actual.


0

Solo una pequeña y limpia plantilla de copiar y pegar de ThorSummoners responde, si está usando Ansible> = 2.3 (la distinción entre archivos y directorios ya no es necesaria).

- 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

Suponiendo que siempre estés en Linux, prueba el findcmd.

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

Esto debería borrar archivos / carpetas / ocultos debajo de /home/mydata/web


1
Puede funcionar, pero el uso del módulo de shell siempre debe ser el último recurso.
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

Este es mi ejemplo.

  1. Instalar repositorio
  2. Instale el paquete rsyslog
  3. detener rsyslog
  4. eliminar todos los archivos dentro de / var / log / rsyslog /
  5. iniciar 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

A continuación funcionó para mí

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

Esto solo confirmará que el directorio existe. Lo creará si no lo hace, pero no hará nada más que informar OK si lo hace.
Chris
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.