Ansible: Bir dizin içindeki dosya ve klasörleri nasıl silebilirim?


152

Aşağıdaki kod yalnızca web dizinine aldığı ilk dosyayı siler. Web dizini içindeki tüm dosya ve klasörleri kaldırmak ve web dizinini korumak istiyorum. Bunu nasıl yapabilirim?

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

Not: rm -rfKomut ve kabuk kullanmayı denedim , ancak çalışmıyorlar. Belki de onları yanlış kullanıyorum.

Doğru yönde herhangi bir yardım takdir edilecektir.

Ansible 2.1.0.0 kullanıyorum


Bir hata gibi görünüyor.
ceving

Yanıtlar:


132

Aşağıdaki kod tüm içeriğini silecek artifact_path

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

Not : Bu, dizini de silecektir.


3
tırnak işareti gerekmez. Bu sadece benim çalışma kodum. artifact_path benzeri / app / my_app / work /
Mohan Kumar P

83
OP (ve ben) klasörün içeriğini silecek bir çözüm istiyor AMA klasörün kendisi DEĞİL. Bu çözüm içeriği VE klasörün kendisini siler.
stokastik

19
Bu nasıl bir oy aldı? Bu, dizini de siler.
deppfx

17
Yukarıdaki kod artifact_path null ile başarısız olan kimse var mı? Bu rm -rf /, tarihteki o harika anlardan birine duyarlı olabileceğini düşünüyor
ted-k42

2
@ ted-k42 Sadece güvenli olmak için böyle bir şey when: artifact_path is defined and artifact_path != ""
yapardım

69

Kabuk modülünü kullanma (aynı zamanda idempotent ):

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

Oluşturma tarihi ve sahibi / izinleri ile ilgilenmiyorsanız en temiz çözüm:

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

7
Çalışıyor ancak ile başlayan dosyaları kaldırmadı. gibi .htaccess
Abbas

Shell de benim için çalıştı. Tam olarak aynı görev ama takas shelliçin commandçalışıyor ve işe yarıyor
SomethingOn

4
Joker karakterler genişleme için bir kabuk gerektirdiklerinden komutla çalışmazlar
JamesP

1
Oluşturma anı sırasında açıkça ayarlamadığınız sürece bunun izinlerinizi / sahibinizi değiştirebileceğini unutmayın.
NeverEndingQueue

Kullanımı kabuk Eğer devlet yerine kabuk rm yoktur = dosya modülünü kullanarak bir uyarı alırsınız. Bunu önlemek için sadece argümanlar
Rodrigo

60

Dizini kaldırın (temel olarak https://stackoverflow.com/a/38201611/1695680 kopyası ), Ansible bu işlemi rmtreebaşlık altında yapar .

- 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

Dizinin tamamını kaldırma ve yeniden oluşturma lüksüne sahip değilseniz, dosyaları (ve dizinleri) tarayabilir ve bunları tek tek silebilirsiniz. Bu biraz zaman alacak. Muhtemelen [ssh_connection]\npipelining = Trueansible.cfg dosyanızda olduğundan emin olmak istersiniz .

- 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
İlk görev gördüğüm en şık çözüm. Eklemek için uzun süredir devam eden bir özellik isteği olduğu başka yerlere yapılan yorumlara dikkat edinstate=empty
William Turrell

24

Gerçekten rm çözümünü sevmedim, ayrıca amible size rm kullanımı hakkında uyarılar veriyor. Yani burada rm'ye ihtiyaç duymadan ve ansible uyarılar olmadan nasıl yapılacağı açıklanmaktadır.

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

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


henüz soru için en iyi çözüm !!
Vsegar

18

Aşağıdaki komutu deneyin, çalışmalı

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

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

3
elde etmek için {{,}} ile son satırdan kaçmayı kaçırdınızwith_items: "{{ contents.stdout_lines }}"
Valerio Crini

lsDosya adlarını almak için 'output' kullanmak tehlikelidir çünkü dosya adlarını yeni satırlar gibi özel karakterlerle doğru yazdırmaz.
bfontaine

5

Tüm yorum ve önerilerden genel olarak yeniden düzenlenmiş ve arızalara karşı güvenli bir uygulama oluşturulmuştur:

# 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

Ne kaçırdığını düşünüyorum registeriçin plugin_dir_deleteddoğru?
Bob Vork

bunu işaret ettiğiniz için teşekkürler. Bu kod parçasını oyun kitaplarımdan birinden çıkardım ve adlandırma açısından daha genel hale getirdim, ancak iki değişken adı değiştirmeyi unutma
Markus

1
İyi şeyler, ama bence son görevde devlet "şimdiki" yerine "dizin" olarak ayarlanması gerekir.
Andrew Allaire

1
İstatistik sonuçlarınızı izinleri korumak için kullanmalısınız: pw_name'den sahip, gr_name'den grup ve moddan mod.
DylanYoung

denedim owner: dir_to_delete.stat.pw_name, group: dir_to_delete.stat.gr_name mode: dir_to_delete.stat.modeama şu anki Ansible sürümümle başarısız oluyor :(
Markus

3

Dosya glob kullanarak da çalışır. Gönderdiğiniz kodda bazı sözdizimi hataları var. Ben değişti ve bu çalışması gerekir test.

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

7
with_fileglobsadece yerel makinede çalışır, uzak makinede değil; doğru değil mi
Stepan Vavra

Doğru .. with_fileglob sadece yerel içindir
Deepali Mittal

Ayrıca, bu dizinleri silmez, sadece dosyalar silinir.
vikas027

2

Ansible hala https://github.com/ansible/ansible-modules-core/issues/902 uygulamak için tartışmaya devam ederkenstate = empty

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

Yine de, senkronizasyon ile dosyalarınızı (silme ile) düzgün bir şekilde senkronize edebilmeniz gerekir.


2

Ben de bunu buluyorum:

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

İlk olarak, birlikte, rehber listeleme alıyoruz find, ayar

  • file_typeiçin any, iç içe geçmiş dizinleri ve bağlantıları kaçırmazdık
  • hidden için yes gizli dosyaları atlamıyoruz
  • Ayrıca, set yok recurseetmek yesdeğil sadece gereksiz olmakla yürütme süresini uzatabilir beri.

Sonra bu listeyi filemodülle inceliyoruz. Çıktısı biraz ayrıntılı, bu nedenle loop_control.labelçıktıyı sınırlandırmamıza yardımcı olacak (bu tavsiyeyi burada bulabilirsiniz ).


Ancak, içeriğin üzerinden yinelendiği için önceki çözümü biraz yavaş buldum, bu yüzden gittim:

- 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 }}"
  • ile dizin özelliklerini al stat
  • dizini sil
  • aynı özelliklere sahip dizini yeniden oluşturun.

Bu benim için yeterliydi, ama isterseniz de ekleyebilirsiniz attributes.


1

Bu konuda açık bir konu var .

Şimdilik çözüm benim için çalışıyor: yerel olarak boş bir klasör oluşturun ve uzak klasörle senkronize edin.

İşte örnek bir oyun kitabı:

- 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

Dosyaları yaş, zaman damgası, glob kalıpları vb.

Ayrıca ansible eski sürümlerle de uyumludur. Bu bulunabilir burada .

İşte bir örnek:

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

0

Bul komutunun sadece dizin içindeki her şeyi sildiğinden emin olmak istiyorum ve benim durumumda dizin bir dosya sistemi olduğundan dizini olduğu gibi bırakıyorum. Bir dosya sistemini silmeye çalışırken sistem bir hata oluşturur ancak bu iyi bir seçenek değildir. Kabuk seçeneğini kullanıyorum çünkü bu soru için şimdiye kadar bulduğum tek çalışma seçeneği bu.

Ben ne yaptım:

Bazı değişkenleri koymak için hosts dosyasını düzenleyin:

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

Ve bir oynatma kitabı oluşturun:

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

Bu, COGNOS_HOME değişken dizinindeki / dosya sistemindeki tüm dosyaları ve dizinleri siler. "-Mindepth 1" seçeneği geçerli dizine dokunulmamasını sağlar.


0

Ansible> = 2.3 kullanıyorsanız, sadece küçük bir temiz kopyala ve yapıştır şablonu ThorSummoners cevabı (artık dosyalar ve dizinler arasındaki ayrım artık gerekli değil.)

- 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

Her zaman Linux'ta olduğunuzu varsayarak cmd'yi deneyin find.

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

Bu işlem gizli dosyaları / klasörleri silmeli /home/mydata/web


1
Çalışabilir, ancak kabuk modülünü kullanmak her zaman son çare olmalıdır.
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

Bu benim örneğim.

  1. Repo yükle
  2. Rsyslog paketini yükle
  3. rsyslog'u durdur
  4. / var / log / rsyslog / içindeki tüm dosyaları sil
  5. rsyslog'u başlat

    - 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şağıda benim için çalıştı,

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

Bu sadece dizinin var olduğunu onaylar. Bunu yapmazsa oluşturur, ancak rapor yoksa Tamam'dan başka bir şey yapmaz.
Chris
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.