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

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

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' для получения имен файлов, потому что он неправильно печатает имена файлов со специальными символами, такими как перевод строки.
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

Я думаю, что вы скучаете 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 }}"

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


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

Я написал специальный модуль 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

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