Ansible: Как удалить файлы и папки внутри каталога?

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
цитаты не обязательны. Это только мой рабочий код. Артефакт_путь похож на / app / my_app / work /
Мохан Кумар П
83
ОП (и я) хотим решение, которое удалит содержимое папки, но НЕ саму папку. Это решение удаляет содержимое и саму папку.
стохастик
19
Как это получило подъем? Это также удаляет каталог.
deppfx
17
Кто-нибудь имел приведенный выше код сбоя на них с artifact_path, равным нулю? Такое ощущение, что это может быть восприимчивым к одному из тех великихrm -rf / моментов в истории
ted-k42
2
@ ted-k42 Я бы сделал что-то подобное, чтобы быть в безопасности:when: artifact_path is defined and artifact_path != ""
bmaupin
69

Используя модуль оболочки ( тоже идемпотент ):

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

Самое чистое решение, если вам не нужны дата создания и владелец / разрешения:

- file: path=/home/mydata/web state=absent
- file: path=/home/mydata/web state=directory
helloV
источник
7
Работает, но не удаляет файлы, начиная с. как .htaccess
Аббас
«Шелл» работал и на меня. Точно такая же задача, но поменялась shellна commandи она работает
SomethingOn
4
Подстановочные знаки не будут работать с командой, так как для их расширения требуется оболочка
JamesP
1
Обратите внимание, что это может изменить ваши разрешения / владельца, если вы не установили явно во время создания.
NeverEndingQueue
Используя оболочку, вы получите предупреждение об использовании файлового модуля с состоянием = отсутствует вместо оболочки rm. Чтобы избежать этого, просто добавьте аргументы: warn: 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
      }}
ThorSummoner
источник
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/

Cris
источник
пока лучшее решение вопроса !!
Всегар
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' для получения имен файлов, потому что он неправильно печатает имена файлов со специальными символами, такими как перевод строки.
17
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
Markus
источник
Я думаю, что вы скучаете registerпо plugin_dir_deleted, верно?
Боб Ворк
Спасибо за указание на это. Я взял этот кусок кода из одной из моих пьес и сделал его более общим с точки зрения именования, но забыл заменить два имени переменных
Маркус
1
Хороший материал, но я думаю, что состояние в последней задаче должно быть установлено как «каталог», а не «присутствует».
Эндрю Аллер
1
Вы должны использовать свой результат статистики, чтобы сохранить права доступа: владелец из pw_name, группа из gr_name и mode из mode.
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/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 }}"

Обратите внимание, что с синхронизацией вы все равно должны иметь возможность правильно синхронизировать ваши файлы (с удалением).

Marcin
источник
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
w1100n
источник
1

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

Он также совместим с более старыми версиями. Это можно найти здесь .

Вот пример:

- cleanup_files:
  path_pattern: /tmp/*.log
  state: absent
  excludes:
    - foo*
    - bar*
Рахул
источник
0

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

Что я сделал:

Отредактируйте файл hosts, добавив некоторые переменные:

[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

Если вы используете Ansible> = 2.3, просто маленький шаблон для копирования и вставки из ThorSummoners (различие между файлами и директориями больше не требуется).

- 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
lanni654321
источник
-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
Сахарам Торат
источник
Это просто подтвердит, что каталог существует. Он создаст его, если он этого не сделает, но ничего не сделает, кроме отчета ОК, если он это сделает.
Крис