Ansible: Làm thế nào để xóa các tập tin và thư mục trong một thư mục?


152

Đoạn mã dưới đây chỉ xóa tệp đầu tiên mà nó nhận được trong thư mục web. Tôi muốn xóa tất cả các tệp và thư mục trong thư mục web và giữ lại thư mục web. Làm thế nào tôi có thể làm điều đó?

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

Lưu ý: Tôi đã thử rm -rfsử dụng lệnh và shell, nhưng chúng không hoạt động. Có lẽ tôi đang sử dụng chúng sai.

Bất kỳ trợ giúp đúng hướng sẽ được đánh giá cao.

Tôi đang sử dụng ansible 2.1.0.0


Trông giống như một con bọ.
ceving

Câu trả lời:


132

Mã bên dưới sẽ xóa toàn bộ nội dung của artifact_path

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

Lưu ý : điều này cũng sẽ xóa thư mục.


3
báo giá không bắt buộc. Đây chỉ là mã làm việc của tôi. artifact_path giống như / app / my_app / work /
Mohan Kumar P

83
OP (và bản thân tôi) muốn một giải pháp sẽ xóa nội dung của thư mục NHƯNG KHÔNG phải chính thư mục đó. Giải pháp này xóa nội dung VÀ chính thư mục.
ngẫu nhiên

19
Làm thế nào điều này có được một upvote? Điều này cũng xóa thư mục.
deppfx

17
Có ai có mã trên thất bại với họ với artifact_path là null không? Cảm giác này có thể dễ bị ảnh hưởng bởi một trong những rm -rf /khoảnh khắc tuyệt vời trong lịch sử
ted-k42

2
@ ted-k42 Tôi sẽ làm một cái gì đó như thế này để đảm bảo an toàn:when: artifact_path is defined and artifact_path != ""
bmaupin

69

Sử dụng mô-đun shell ( idempotent quá):

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

Giải pháp sạch nhất nếu bạn không quan tâm đến ngày tạo và chủ sở hữu / quyền:

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

7
Hoạt động nhưng không loại bỏ các tập tin bắt đầu với. như .htaccess
Abbas

Shell cũng làm việc cho tôi. Nhiệm vụ chính xác tương tự nhưng đổi shelltrong cho commandvà nó hoạt động
SomethingOn

4
Ký tự đại diện sẽ không hoạt động với lệnh khi chúng cần vỏ để mở rộng
JamesP

1
Lưu ý rằng điều này có thể thay đổi quyền / chủ sở hữu của bạn trừ khi bạn đặt rõ ràng trong thời điểm tạo.
NeverEinatingQueue

Sử dụng shell, bạn sẽ nhận được cảnh báo về việc sử dụng mô-đun tệp có trạng thái = vắng mặt thay vì shell rm. Để tránh điều đó, chỉ cần thêm args: warn: false
Rodrigo

60

Xóa thư mục (về cơ bản là bản sao của https://stackoverflow.com/a/38201611/1695680 ), Ansible thực hiện thao tác này với rmtreebên dưới mui xe.

- 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

Nếu bạn không muốn xóa toàn bộ thư mục và tạo lại nó, bạn có thể quét nó để tìm các tệp, (và thư mục) và xóa từng thư mục một. Mà sẽ mất một lúc. Bạn có thể muốn chắc chắn rằng bạn có [ssh_connection]\npipelining = Truetrong ansible.cfg của bạn trên.

- 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
Nhiệm vụ đầu tiên là giải pháp tao nhã nhất mà tôi từng thấy. Lưu ý các ý kiến ​​ở nơi khác có yêu cầu tính năng dài hạn để thêmstate=empty
William Turrell

24

Tôi thực sự không thích giải pháp rm, cũng có thể đưa ra cảnh báo cho bạn về việc sử dụng rm. Vì vậy, đây là cách để làm điều đó mà không cần rm và không có cảnh báo ansible.

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

nguồn: http://www.mydailytutorials.com/ansible-delete-multipl-files-directories-ansible/


nhưng giải pháp tốt nhất cho câu hỏi !!
Vsegar

18

Hãy thử lệnh dưới đây, nó sẽ hoạt động

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

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

3
bạn đã bỏ lỡ để thoát chính xác dòng cuối cùng với {{,}} để có đượcwith_items: "{{ contents.stdout_lines }}"
Valerio Crini

Thật nguy hiểm khi sử dụng ls'đầu ra để lấy tên tệp vì nó không in đúng tên tệp với các ký tự đặc biệt như dòng mới.
bfontaine

5

Tạo ra một triển khai tổng thể được cải tạo và không an toàn từ tất cả các ý kiến ​​và đề xuất:

# 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

Tôi nghĩ rằng bạn đang thiếu registercho plugin_dir_deleted, phải không?
Bob Vork

cảm ơn đã chỉ ra điều này Tôi đã lấy đoạn mã này ra khỏi một trong những cuốn sách của mình và làm cho nó chung chung hơn về cách đặt tên nhưng quên thay thế hai tên biến
Markus

1
Thứ tốt, nhưng tôi nghĩ trạng thái trong tác vụ cuối cùng cần được đặt thành "thư mục" thay vì "hiện tại".
Andrew Allaire

1
Bạn nên sử dụng kết quả thống kê của mình để giữ quyền: chủ sở hữu từ pw_name, nhóm từ gr_name và chế độ từ chế độ.
DylanYoung

đã thử owner: dir_to_delete.stat.pw_name, group: dir_to_delete.stat.gr_name mode: dir_to_delete.stat.modenhưng nó không thành công với phiên bản Ansible hiện tại của tôi :(
Markus

3

Sử dụng tập tin toàn cầu nó cũng sẽ làm việc. Có một số lỗi cú pháp trong mã bạn đã đăng. Tôi đã sửa đổi và thử nghiệm điều này sẽ làm việc.

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

7
with_fileglobchỉ hoạt động trên máy cục bộ, không phải từ xa; không phải vậy sao
Stepan Vavra

Đúng .. with_fileglob chỉ dành cho địa phương
Deepali Mittal

Ngoài ra, điều này không xóa các thư mục, chỉ các tập tin bị xóa.
vikas027

2

Trong khi Ansible vẫn đang tranh luận để triển khai 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 }}"

Lưu ý rằng, với việc đồng bộ hóa, bạn vẫn có thể đồng bộ hóa các tệp của mình (có xóa) đúng cách.


2

Đó là những gì tôi nghĩ ra:

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

Đầu tiên, chúng tôi sẽ nhận được danh sách thư mục với find, cài đặt

  • file_typeđể any, vì vậy chúng tôi sẽ không bỏ lỡ các thư mục và liên kết lồng nhau
  • hiddenđể yes, vì vậy chúng tôi không bỏ qua các tập tin ẩn
  • Ngoài ra, không được đặt recursethành yes, vì nó không chỉ không cần thiết mà còn có thể tăng thời gian thực hiện.

Sau đó, chúng tôi đi qua danh sách đó với filemô-đun. Đầu ra của nó hơi dài dòng, vì vậy loop_control.labelsẽ giúp chúng tôi hạn chế đầu ra (tìm thấy lời khuyên này ở đây ).


Nhưng tôi thấy giải pháp trước đây hơi chậm, vì nó lặp đi lặp lại qua nội dung, vì vậy tôi đã đi với:

- 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 }}"
  • có được thuộc tính thư mục với stat
  • xóa thư mục
  • tạo lại thư mục với các thuộc tính tương tự.

Điều đó là đủ cho tôi, nhưng bạn cũng có thể thêm attributes, nếu bạn muốn.


1

Có một vấn đề mở đối với điều này.

Hiện tại, giải pháp hoạt động với tôi: tạo một thư mục trống cục bộ và đồng bộ hóa nó với thư mục từ xa.

Dưới đây là một mẫu playbook:

- 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

Tôi đã viết một mô-đun ansible tùy chỉnh để dọn dẹp các tệp dựa trên nhiều bộ lọc như tuổi, dấu thời gian, mẫu hình cầu, v.v.

Nó cũng tương thích với các phiên bản cũ hơn. Nó có thể được tìm thấy ở đây .

Đây là một ví dụ:

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

0

Tôi muốn chắc chắn rằng lệnh find chỉ xóa mọi thứ bên trong thư mục và giữ nguyên thư mục vì trong trường hợp của tôi, thư mục là một hệ thống tập tin. Hệ thống sẽ tạo ra một lỗi khi cố gắng xóa một hệ thống tập tin nhưng đó không phải là một lựa chọn tốt. Tôi sử dụng tùy chọn shell bởi vì đó là tùy chọn làm việc duy nhất tôi tìm thấy cho đến nay cho câu hỏi này.

Tôi đã làm gì:

Chỉnh sửa tệp máy chủ để đặt một số biến:

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

Và tạo một cuốn sách:

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

Điều này sẽ xóa tất cả các tệp và thư mục trong thư mục / hệ thống tệp biến COGNOS_HOME. Tùy chọn "-mindepth 1" đảm bảo rằng thư mục hiện tại sẽ không bị chạm.


0

Chỉ cần một bản sao và dán mẫu sạch hơn của câu trả lời ThorSummoners, nếu bạn đang sử dụng Ansible> = 2.3 (phân biệt giữa các tệp và thư mục không cần thiết nữa.)

- 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

Giả sử bạn luôn ở trong Linux, hãy thử findcmd.

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

Điều này sẽ xóa sạch các tập tin / thư mục / ẩn dưới /home/mydata/web


1
Nó có thể hoạt động nhưng sử dụng mô-đun shell phải luôn là giải pháp cuối cùng.
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

Đây là ví dụ của tôi.

  1. Cài đặt repo
  2. Cài đặt gói rsyslog
  3. dừng rsyslog
  4. xóa tất cả các tệp bên trong / var / log / rsyslog /
  5. bắt đầu 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

Dưới đây làm việc cho tôi,

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

Điều này sẽ chỉ xác nhận rằng thư mục tồn tại. Nó sẽ tạo ra nó nếu không nhưng không làm gì khác ngoài báo cáo OK nếu có.
Chris
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.