Ansible: Jak usunąć pliki i foldery w katalogu?

152

Poniższy kod usuwa tylko pierwszy plik, który dostaje się do katalogu internetowego. Chcę usunąć wszystkie pliki i foldery w katalogu internetowym i zachować katalog WWW. Jak mogę to zrobić?

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

Uwaga: próbowałem rm -rfużyć polecenia i powłoki, ale nie działają. Być może niewłaściwie ich używam.

Każda pomoc we właściwym kierunku zostanie doceniona.

Używam ansible 2.1.0.0

Abbas
źródło
Wygląda na błąd.
ceving

Odpowiedzi:

132

Poniższy kod usunie całą zawartość artifact_path

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

Uwaga : spowoduje to również usunięcie katalogu.

Mohan Kumar P.
źródło
3
cytaty nie są wymagane. To jest tylko mój działający kod. artifact_path is like / app / my_app / work /
Mohan Kumar P
83
OP (i ja) chcemy rozwiązania, które usunie zawartość folderu, ALE NIE samego folderu. To rozwiązanie usuwa zawartość ORAZ sam folder.
stochastyczny
19
Jak to się zyskało? Spowoduje to również usunięcie katalogu.
deppfx
17
Czy ktoś miał na nich błąd powyższego kodu i wartość artifact_path ma wartość null? To wydaje się być podatne na jeden z tych wielkich rm -rf /momentów w historii
ted-k42
2
@ ted-k42 Zrobiłbym coś takiego dla pewności:when: artifact_path is defined and artifact_path != ""
bmaupin
69

Korzystanie z modułu powłoki ( również idempotentny ):

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

Najczystsze rozwiązanie, jeśli nie zależy Ci na dacie utworzenia i właścicielu / uprawnieniach:

- file: path=/home/mydata/web state=absent
- file: path=/home/mydata/web state=directory
cześć V.
źródło
7
Działa, ale nie usuwa plików zaczynających się od. jak .htaccess
Abbas
Shell też u mnie pracował. Dokładnie to samo zadanie, ale zamienione shellna commandi działa
SomethingOn
4
Symbole wieloznaczne nie będą działać z poleceniem, ponieważ wymagają powłoki do rozszerzenia
JamesP
1
Zwróć uwagę, że może to zmienić twoje uprawnienia / właściciela, chyba że ustawisz to jawnie w momencie tworzenia.
NeverEndingQueue
Używając powłoki , otrzymasz ostrzeżenie o używaniu modułu pliku ze stanem = nieobecny zamiast powłoki rm. Aby tego uniknąć, po prostu dodaj argumenty: warn: false
Rodrigo
60

Usuń katalog (w zasadzie kopię https://stackoverflow.com/a/38201611/1695680 ), Ansible wykonuje tę operację rmtreepod maską.

- 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

Jeśli nie masz luksusu usunięcia całego katalogu i odtworzenia go, możesz przeskanować go w poszukiwaniu plików (i katalogów) i usuwać je jeden po drugim. Co trochę potrwa. Prawdopodobnie chcesz się upewnić, że masz [ssh_connection]\npipelining = Truewłączony plik 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
źródło
6
Pierwsze zadanie to najbardziej eleganckie rozwiązanie, jakie widziałem. Zwróć uwagę na komentarze w innym miejscu, że istnieje długo działająca prośba o dodanie funkcjistate=empty
William Turrell
24

Naprawdę nie podobało mi się rozwiązanie rm, a także ansibl ostrzega o używaniu rm. Oto jak to zrobić bez potrzeby rm i bez ostrzeżeń ansibli.

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

źródło: http://www.mydailytutorials.com/ansible-delete-multiple-files-directories-ansible/

Kryzys
źródło
jeszcze najlepsze rozwiązanie na to pytanie !!
Vsegar
18

spróbuj poniższego polecenia, powinno działać

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

- file: path=/some/dir/{{ item }} state=absent
  with_items: {{ contents.stdout_lines }}
Ganesan Srinivasan
źródło
3
przegapiłeś poprawną ucieczkę z ostatniej linii z {{,}}, aby uzyskaćwith_items: "{{ contents.stdout_lines }}"
Valerio Crini
Używanie funkcji ls„output” do pobierania nazw plików jest niebezpieczne, ponieważ nie wyświetla poprawnie nazw plików ze znakami specjalnymi, takimi jak znaki nowej linii.
bfontaine
5

Na podstawie wszystkich komentarzy i sugestii utworzono całkowicie odnowioną i bezpieczną implementację:

# 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
źródło
Myślę, że brakuje ci registerfor plugin_dir_deleted, prawda?
Bob Vork,
dzięki za wskazanie tego. Wyciągnąłem ten fragment kodu z jednego z moich poradników i uczyniłem go bardziej ogólnym pod względem nazewnictwa, ale zapomniałem zastąpić dwie nazwy zmiennych
Markus,
1
Dobra rzecz, ale myślę, że stan w ostatnim zadaniu musi być ustawiony na „katalog”, a nie na „obecny”.
Andrew Allaire
1
Powinieneś użyć swojego wyniku statystycznego, aby zachować uprawnienia: właściciel z pw_name, grupa z gr_name i tryb z trybu.
DylanYoung
próbowałem, owner: dir_to_delete.stat.pw_name, group: dir_to_delete.stat.gr_name mode: dir_to_delete.stat.modeale nie udaje mi się z moją aktualną wersją Ansible :(
Markus
3

Używanie pliku glob również zadziała. W opublikowanym kodzie występuje błąd składni. Zmodyfikowałem i przetestowałem to powinno działać.

- name: remove web dir contents
  file:
    path: "{{ item }}"
    state: absent
  with_fileglob:
    - "/home/mydata/web/*"
Deepali Mittal
źródło
7
with_fileglobdziała tylko na komputerze lokalnym, a nie zdalnym; czy to nie prawda?
Stepan Vavra
To prawda ... with_fileglob jest tylko dla lokalnych
Deepali Mittal
Ponadto nie usuwa to katalogów, tylko pliki są usuwane.
vikas027
2

Podczas gdy Ansible wciąż debatuje nad wdrożeniem 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 }}"

Pamiętaj jednak, że dzięki synchronizacji powinieneś być w stanie poprawnie zsynchronizować swoje pliki (z usuwaniem).

Marcin
źródło
2

Oto, co wymyśliłem:

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

Po pierwsze, otrzymujemy listę katalogów z findustawieniem

  • file_type do any , aby nie przegapić zagnieżdżonych katalogów i linków
  • hidden do yes , więc nie pomijamy ukrytych plików
  • również nie ustawiaj recursena yes, ponieważ jest to nie tylko niepotrzebne, ale może wydłużyć czas wykonania.

Następnie przeglądamy tę listę za pomocą filemodule. Jego wynik jest nieco rozwlekły, więc loop_control.labelpomoże nam w ograniczaniu wyjścia (znalazłem tę radę tutaj ).


Ale okazało się, że poprzednie rozwiązanie jest nieco powolne, ponieważ iteruje po zawartości, więc poszedłem z:

- 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 }}"
  • pobierz właściwości katalogu za pomocą stat
  • usuń katalog
  • odtworzyć katalog z tymi samymi właściwościami.

To mi wystarczyło, ale możesz też dodać attributes, jeśli chcesz.

Alexander
źródło
1

W związku z tym istnieje otwarta kwestia .

Na razie rozwiązanie działa dla mnie: utwórz pusty folder lokalnie i zsynchronizuj go ze zdalnym.

Oto przykładowy poradnik:

- 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
źródło
1

Napisałem niestandardowy moduł ansible do czyszczenia plików w oparciu o wiele filtrów, takich jak wiek, sygnatura czasowa, wzorce glob itp.

Jest również kompatybilny ze starszymi wersjami ansible. Można go znaleźć tutaj .

Oto przykład:

- cleanup_files:
  path_pattern: /tmp/*.log
  state: absent
  excludes:
    - foo*
    - bar*
Rahul
źródło
0

Chcę się upewnić, że polecenie find usuwa tylko wszystko z katalogu i pozostawia katalog nienaruszony, ponieważ w moim przypadku katalog jest systemem plików. System wygeneruje błąd podczas próby usunięcia systemu plików, ale nie jest to dobra opcja. Używam opcji powłoki, ponieważ jest to jedyna działająca opcja, jaką do tej pory znalazłem dla tego pytania.

Co ja zrobiłem:

Edytuj plik hosts, aby wstawić kilka zmiennych:

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

I utwórz poradnik:

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

Spowoduje to usunięcie wszystkich plików i katalogów w katalogu zmiennych / systemie plików COGNOS_HOME. Opcja „-mindepth 1” zapewnia, że ​​bieżący katalog nie zostanie dotknięty.

Tjerk Maij
źródło
0

Po prostu mały, czystszy szablon kopiowania i wklejania ThorSummoners odpowiada, jeśli używasz Ansible> = 2.3 (rozróżnienie między plikami i katalogami nie jest już konieczne).

- 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
Enno Gröper
źródło
-1

Zakładając, że zawsze korzystasz z Linuksa, wypróbuj findcmd.

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

Powinno to usunąć pliki / foldery / ukryte pod /home/mydata/web

Sherzod Odinaev
źródło
1
Może to działać, ale używanie modułu powłoki powinno być zawsze ostatecznością.
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
lanni654321
źródło
-4

To jest mój przykład.

  1. Zainstaluj repozytorium
  2. Zainstaluj pakiet rsyslog
  3. zatrzymaj rsyslog
  4. usuń wszystkie pliki w / var / log / rsyslog /
  5. uruchom 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
    
Satish
źródło
-6

Poniżej pracował dla mnie,

- name: Ansible delete html directory
  file:
   path: /var/www/html
   state: directory
Sakharam Thorat
źródło
To tylko potwierdzi, że katalog istnieje. Utworzy go, jeśli nie, ale nie zrobi nic poza raportem OK, jeśli tak.
Chris,