Ansible: Bagaimana cara menghapus file dan folder di dalam direktori?

152

Kode di bawah ini hanya menghapus file pertama yang didapat di dalam dir web. Saya ingin menghapus semua file dan folder di dalam direktori web dan menyimpan direktori web. Bagaimana saya bisa melakukan itu?

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

Catatan: Saya sudah mencoba rm -rfmenggunakan perintah dan shell, tetapi tidak berfungsi. Mungkin saya salah menggunakannya.

Bantuan apa pun di arah yang benar akan dihargai.

Saya menggunakan 2.1.0.0 yang memungkinkan

Abbas
sumber
Tampak seperti bug.
ceving

Jawaban:

132

Kode di bawah ini akan menghapus seluruh konten artifact_path

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

Catatan : ini juga akan menghapus direktori.

Mohan Kumar P
sumber
3
kutipan tidak diperlukan. Ini hanya kode kerja saya. artifact_path seperti / app / my_app / work /
Mohan Kumar P
83
OP (dan saya sendiri) menginginkan solusi yang akan menghapus isi folder TAPI BUKAN folder itu sendiri. Solusi ini menghapus konten DAN folder itu sendiri.
stochastic
19
Bagaimana ini bisa mendapat dukungan? Ini juga menghapus direktori.
deppfx
17
Adakah yang punya kode di atas gagal pada mereka dengan artifact_path menjadi nol? Ini terasa seperti rentan terhadap salah satu rm -rf /momen hebat dalam sejarah
ted-k42
2
@ ted-k42 Saya akan melakukan sesuatu seperti ini hanya untuk aman:when: artifact_path is defined and artifact_path != ""
bmaupin
69

Menggunakan modul shell ( idempoten juga):

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

Solusi terbersih jika Anda tidak peduli tentang tanggal pembuatan dan pemilik / izin:

- file: path=/home/mydata/web state=absent
- file: path=/home/mydata/web state=directory
haloV
sumber
7
Bekerja tetapi tidak menghapus file yang dimulai dengan. seperti .htaccess
Abbas
Shell juga bekerja untukku. Tugas yang sama persis tetapi bertukar shelluntuk commanddan berfungsi
SomethingOn
4
Wildcard tidak akan bekerja dengan perintah karena mereka membutuhkan shell untuk ekspansi
JamesP
1
Perhatikan bahwa ini dapat mengubah izin / pemilik Anda kecuali Anda menetapkan secara eksplisit selama momen pembuatan.
NeverEndingQueue
Menggunakan shell, Anda akan mendapat peringatan untuk menggunakan modul file dengan status = tidak ada, bukan shell rm. Untuk menghindarinya tambahkan saja args: warn: false
Rodrigo
60

Hapus direktori (pada dasarnya salinan https://stackoverflow.com/a/38201611/1695680 ), mungkin melakukan operasi ini dengan di rmtreebawah tenda.

- 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

Jika Anda tidak memiliki kemewahan untuk menghapus seluruh direktori dan membuatnya kembali, Anda dapat memindai file, (dan direktori), dan menghapusnya satu per satu. Yang akan memakan waktu cukup lama. Anda mungkin ingin memastikan bahwa Anda telah [ssh_connection]\npipelining = Truemengaktifkan an.cfg di.

- 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
sumber
6
Tugas pertama adalah solusi paling elegan yang pernah saya lihat. Perhatikan komentar di tempat lain bahwa ada permintaan fitur yang sudah lama ditambahkanstate=empty
William Turrell
24

Saya benar-benar tidak suka solusi rm, juga memungkinkan memberi Anda peringatan tentang penggunaan rm. Jadi di sini adalah bagaimana melakukannya tanpa perlu rm dan tanpa peringatan yang memungkinkan.

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

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

Cris
sumber
namun solusi terbaik untuk pertanyaan !!
Vsegar
18

coba perintah di bawah ini, itu harus bekerja

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

- file: path=/some/dir/{{ item }} state=absent
  with_items: {{ contents.stdout_lines }}
Ganesan Srinivasan
sumber
3
Anda ketinggalan untuk keluar dengan benar dari baris terakhir dengan {{,}} untuk mendapatkanwith_items: "{{ contents.stdout_lines }}"
Valerio Crini
Berbahaya menggunakan lskeluaran 'untuk mendapatkan nama file karena tidak benar mencetak nama file dengan karakter khusus seperti baris baru.
bfontaine
5

Menciptakan implementasi keseluruhan yang direhaul dan gagal-aman dari semua komentar dan saran:

# 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
sumber
Saya pikir Anda kehilangan registeruntuk plugin_dir_deleted, kan?
Bob Vork
terima kasih telah menunjukkan ini. Saya memiliki kode ini yang diambil dari salah satu buku pedoman saya dan membuatnya lebih umum dalam hal penamaan tetapi lupa untuk mengganti dua nama variabel
Markus
1
Bagus, tapi saya pikir keadaan di tugas terakhir harus diatur ke "direktori" daripada "sekarang".
Andrew Allaire
1
Anda harus menggunakan hasil stat Anda untuk mempertahankan izin: pemilik dari pw_name, grup dari gr_name, dan mode dari mode.
DylanYoung
mencoba owner: dir_to_delete.stat.pw_name, group: dir_to_delete.stat.gr_name mode: dir_to_delete.stat.modetetapi gagal pada saya dengan versi Ansible saya saat ini :(
Markus
3

Menggunakan file glob juga akan berfungsi. Ada beberapa kesalahan sintaksis dalam kode yang Anda posting. Saya telah memodifikasi dan menguji ini harus bekerja.

- name: remove web dir contents
  file:
    path: "{{ item }}"
    state: absent
  with_fileglob:
    - "/home/mydata/web/*"
Deepali Mittal
sumber
7
with_fileglobhanya bekerja pada mesin lokal, bukan yang jauh; bukankah itu benar
Stepan Vavra
Benar .. with_fileglob hanya untuk lokal
Deepali Mittal
Juga, ini tidak menghapus direktori, hanya file yang dihapus.
vikas027
2

Sementara Ansible masih berdebat untuk menerapkan 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 }}"

Namun perlu dicatat, dengan sinkronisasi Anda tetap dapat menyinkronkan file Anda (dengan menghapus) dengan benar.

Marcin
sumber
2

Itulah yang saya kemukakan:

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

Pertama, kita mendapatkan daftar direktori find, pengaturan

  • file_typeuntuk any, jadi kami tidak akan melewatkan direktori dan tautan yang bersarang
  • hiddenuntuk yes, jadi kami tidak melewatkan file tersembunyi
  • juga, jangan diatur recurseke yes, karena tidak hanya tidak perlu, tetapi dapat menambah waktu eksekusi.

Kemudian, kita melihat daftar itu dengan filemodul. Outputnya sedikit bertele-tele, jadi loop_control.labelakan membantu kami membatasi output (temukan saran ini di sini ).


Tetapi saya menemukan solusi sebelumnya agak lambat, karena iterates melalui konten, jadi saya pergi dengan:

- 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 }}"
  • dapatkan properti direktori dengan stat
  • hapus direktori
  • buat ulang direktori dengan properti yang sama.

Itu sudah cukup bagi saya, tetapi Anda dapat menambahkan attributesjuga, jika Anda mau.

Alexander
sumber
1

Ada masalah terbuka sehubungan dengan ini.

Untuk saat ini, solusinya berfungsi untuk saya: buat folder kosong secara lokal dan sinkronkan dengan yang jauh.

Berikut ini adalah contoh buku pedoman:

- 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
sumber
1

Saya telah menulis modul yang memungkinkan kustom untuk membersihkan file berdasarkan beberapa filter seperti usia, timestamp, pola glob, dll.

Ini juga kompatibel dengan versi lama yang mungkin. Itu dapat ditemukan di sini .

Berikut ini sebuah contoh:

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

Saya ingin memastikan bahwa perintah find hanya menghapus semua yang ada di dalam direktori dan membiarkan direktori tetap utuh karena dalam kasus saya direktori tersebut adalah sistem file. Sistem akan menghasilkan kesalahan ketika mencoba menghapus sistem file tetapi itu bukan pilihan yang bagus. Saya menggunakan opsi shell karena itu adalah satu-satunya opsi yang saya temukan sejauh ini untuk pertanyaan ini.

Apa yang saya lakukan:

Edit file host untuk dimasukkan ke dalam beberapa variabel:

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

Dan buat buku pedoman:

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

Ini akan menghapus semua file dan direktori di direktori variabel / sistem file COGNOS_HOME. Opsi "-mindepth 1" memastikan bahwa direktori saat ini tidak akan disentuh.

Tjerk Maij
sumber
0

Hanya sedikit salin bersih & tempel templat jawaban ThorSummoners, jika Anda menggunakan Ansible> = 2.3 (perbedaan antara file dan direktori tidak diperlukan lagi.)

- 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
sumber
-1

Dengan asumsi Anda selalu berada di Linux, coba findcmd.

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

Ini harus menghapus file / folder / tersembunyi di bawah /home/mydata/web

Sherzod Odinaev
sumber
1
Mungkin berhasil tetapi menggunakan modul shell harus selalu menjadi pilihan terakhir.
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
sumber
-4

Ini adalah contoh saya.

  1. Pasang repo
  2. Instal paket rsyslog
  3. hentikan rsyslog
  4. hapus semua file di dalam / var / log / rsyslog /
  5. mulai 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
sumber
-6

Di bawah ini bekerja untuk saya,

- name: Ansible delete html directory
  file:
   path: /var/www/html
   state: directory
Sakharam Thorat
sumber
Ini hanya akan mengkonfirmasi bahwa direktori tersebut ada. Ini akan membuatnya jika tidak tetapi tidak melakukan apa-apa selain melaporkan OK jika tidak.
Chris