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


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.


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

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

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/


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

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

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/*"

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.


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.


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

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*

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.


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

-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


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

-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
    

-6

Di bawah ini bekerja untuk saya,

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

Ini hanya akan mengkonfirmasi bahwa direktori tersebut ada. Ini akan membuatnya jika tidak tetapi tidak melakukan apa-apa selain melaporkan OK jika tidak.
Chris
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.