Відповідь: Як видалити файли та папки всередині каталогу?


152

Нижче наведений код видаляє лише перший файл, який він отримує всередині веб-реєстру. Я хочу видалити всі файли та папки з веб-каталогу та зберегти веб-каталог. Як я можу це зробити?

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

Примітка. Я намагався rm -rfвикористовувати команду та оболонку, але вони не працюють. Можливо, я їх неправильно використовую.

Будь-яка допомога в правильному напрямку буде вдячна.

Я використовую ansible 2.1.0.0


Схоже на помилку.
припинення

Відповіді:


132

Нижче коду буде видалено весь вміст artifact_path

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

Примітка : це також видалить каталог.


3
котирування не потрібні. Це лише мій робочий код. artifact_path - це / app / my_app / work /
Mohan Kumar P

83
ОП (і я сам) хочу рішення, яке видалить вміст папки, АМЕ НЕ сама папка. Це рішення видаляє вміст І саму папку.
стохастичний

19
Як це отримало надбавку? Це також видаляє каталог.
deppfx

17
Хтось із цих кодів вийшов з ладу на них, артефакт_пат є нульовим? Це здається, що це може сприйняти один з тих чудових rm -rf /моментів в історії
ted-k42

2
@ ted-k42 Я зробив би щось подібне лише для того, щоб бути в безпеці:when: artifact_path is defined and artifact_path != ""
bmaupin

69

Використання модуля оболонки ( теж idempotent ):

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

Найпростіше рішення, якщо вам не важливо дата створення та власник / дозволи:

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

7
Працює, але не видалив файли, починаючи з. як .htaccess
Аббас

Shell працював і для мене. Точне завдання, але замінено shellна commandце, і воно працює
Щось

4
Уайлдкард не працюватиме з командою, оскільки для розширення потрібна оболонка
JamesP

1
Зауважте, що це може змінити ваші дозволи / власника, якщо ви прямо не встановите це в момент створення.
NeverEndingQueue

Використовуючи оболонку, ви отримаєте попередження про використання модуля файлів з state = відсутнім замість оболонки rm. Щоб уникнути цього, додайте аргументи: попереджайте: false
Родріго

60

Видаліть каталог (в основному це копія https://stackoverflow.com/a/38201611/1695680 ), Ansible робить цю операцію rmtreeпід кришкою.

- 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

Якщо ви не маєте розкоші видаляти весь каталог та відтворювати його, ви можете сканувати його на файли (та каталоги) та видаляти їх по одному. Що займе певний час. Ви, ймовірно, хочете переконатися, що у вас є [ssh_connection]\npipelining = Trueсвій ansible.cfg.

- 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
Перше завдання - це найелегантніше рішення, яке я бачив. Зверніть увагу на коментарі в інших місцях, що є тривалий запит на додавання функціїstate=empty
Вільям Туррелл

24

Мені дуже не сподобалося рішення rm, також ansible дає вам попередження щодо використання rm. Тож ось як це зробити без потреби rm та без ангібельних попереджень.

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

джерело: http://www.mydailytutorials.com/ansible-delete-multiple-files-directories-ansible/


все-таки найкраще рішення питання !!
Всегар

18

спробуйте команду нижче, вона повинна працювати

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

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

3
ви пропустили правильний втечу з останнього рядка з {{,}}, щоб отриматиwith_items: "{{ contents.stdout_lines }}"
Валеріо Кріні

Використовувати ls'output' для отримання імен файлів небезпечно, оскільки він неправильно друкує назви файлів спеціальними символами, такими як нові рядки.
bfontaine

5

З усіх коментарів та пропозицій створено загальну перероблену та безвідмовну реалізацію:

# 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

Я думаю , ви пропустили registerна plugin_dir_deleted, НЕ так?
Боб Ворк

дякую, що вказали на це. У мене цей фрагмент коду був вийнятий з однієї з моїх ігрових книжок і зробив його більш загальним у плані називання, але забудьте замінити два назви змінних
Маркус

1
Хороший матеріал, але я думаю, що стан в останньому завданні потрібно встановити на "каталог", а не на "присутній".
Ендрю Аллер

1
Ви повинні використовувати результат stat для збереження дозволів: власник від pw_name, група від gr_name та режим з режиму.
DylanYoung

спробував, owner: dir_to_delete.stat.pw_name, group: dir_to_delete.stat.gr_name mode: dir_to_delete.stat.modeале мені не
Маркус

3

Використання файлового глобула також буде працювати. У коді, який ви опублікували, є синтаксична помилка. Я змінив і протестував це повинно працювати.

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

7
with_fileglobпрацює лише на локальній машині, а не на віддаленій; чи не правда?
Степан Вавра

Правда .. with_fileglob призначений лише для місцевих
Deepali Mittal

Крім того, це не видаляє каталоги, просто файли видаляються.
vikas027

2

Поки Ansible все ще обговорює питання про реалізацію state = empty https://github.com/ansible/ansible-modules-core/isissue/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 }}"

Зауважте, що при синхронізації ви в будь-якому разі маєте змогу належним чином синхронізувати файли (із видаленням)


2

Ось що я придумав:

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

По-перше, ми отримуємо список каталогу find, налаштування

  • file_typeдо any, щоб ми не пропустили вкладені каталоги та посилання
  • hiddenщоб yesми не пропускали приховані файли
  • Крім того , не встановлено recurseна yes, так як це не тільки непотрібним, але може збільшити час виконання.

Потім ми переходимо через цей список з fileмодулем. Вихід є трохи дослідним, тому loop_control.labelдопоможе нам обмежити вихід (цю пораду знайдено тут ).


Але я знайшов попереднє рішення дещо повільним, оскільки воно перебирає вміст, тому я пішов із:

- 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 }}"
  • отримати властивості каталогу за допомогою stat
  • видалити каталог
  • відтворити каталог з тими ж властивостями.

Цього мені було достатньо, але ви можете також додати attributes, якщо хочете.


1

З цього приводу існує відкрите питання .

Наразі рішення працює для мене: створити порожню папку локально та синхронізувати її з віддаленою.

Ось зразок ігрової книги:

- 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

Я написав користувальницький модуль ансибілізації для очищення файлів на основі декількох фільтрів, таких як вік, часові позначки, шаблони глобальних і т.д.

Він також сумісний з відповідальнішими старими версіями. Його можна знайти тут .

Ось приклад:

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

0

Я хочу переконатися, що команда find видаляє лише все, що знаходиться всередині каталогу, а каталог залишається недоторканим, оскільки в моєму випадку каталог є файловою системою. Система генерує помилку при спробі видалити файлову систему, але це не приємний варіант. Я використовую варіант оболонки, тому що це єдиний робочий варіант, який я знайшов поки що для цього питання.

Що я зробив:

Відредагуйте файл хостів, щоб ввести деякі змінні:

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

І створіть ігрову книжку:

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

Це видалить усі файли та каталоги в каталозі / файловій системі змінних COGNOS_HOME. Параметр "-mindepth 1" гарантує, що поточний каталог не буде торкатися.


0

Лише невеликий шаблон чистішого копіювання та вставки шаблону відповіді ThorSummoners, якщо ви використовуєте Ansible> = 2.3 (розрізнення між файлами та dirs більше не потрібно).

- 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

Якщо припустити, що ви завжди в Linux, спробуйте findcmd.

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

Це має стерти файли / папки / приховані під /home/mydata/web


1
Це може працювати, але використання модуля оболонки завжди має бути крайнім засобом.
Кріс

-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

Це мій приклад.

  1. Встановити репо
  2. Встановіть пакет rsyslog
  3. зупинити rsyslog
  4. видалити всі файли всередині / var / log / rsyslog /
  5. запустити 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

Нижче працював для мене,

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

Це просто підтвердить існування каталогу. Він створить його, якщо він не зробить, але не зробить нічого іншого, окрім звіту "ОК", якщо він є.
Кріс
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.