Ansible: วิธีลบไฟล์และโฟลเดอร์ในไดเรกทอรี?


152

รหัสด้านล่างจะลบไฟล์แรกที่ได้รับภายในเว็บเท่านั้น ฉันต้องการลบไฟล์และโฟลเดอร์ทั้งหมดที่อยู่ในสารบบเว็บและเก็บสารบบเว็บ ฉันจะทำสิ่งนั้นได้อย่างไร

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

หมายเหตุ: ฉันได้ลองแล้ว rm -rfใช้คำสั่งและเปลือก แต่พวกเขาไม่ทำงาน บางทีฉันกำลังใช้พวกเขาผิด

ความช่วยเหลือในทิศทางที่ถูกต้องจะได้รับการชื่นชม

ฉันกำลังใช้ ansible 2.1.0.0


ดูเหมือนข้อผิดพลาด
ceving

คำตอบ:


132

โค้ดด้านล่างจะลบเนื้อหาทั้งหมดของ artifact_path

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

หมายเหตุ : นี่จะลบไดเรกทอรีด้วย


3
ไม่จำเป็นต้องใส่เครื่องหมายคำพูด นี่คือรหัสการทำงานของฉันเท่านั้น ifact_path เป็นเหมือน / app / my_app / work /
Mohan Kumar P

83
OP (และตัวฉันเอง) ต้องการโซลูชันที่จะลบเนื้อหาของโฟลเดอร์ แต่ไม่ใช่โฟลเดอร์ วิธีนี้จะลบเนื้อหาและโฟลเดอร์เอง
สุ่ม

19
สิ่งนี้ได้รับการโหวตอย่างไร นี่เป็นการลบไดเรกทอรีด้วย
deppfx

17
มีใครมีรหัสข้างต้นล้มเหลวพวกเขาด้วยifact_pathเป็นโมฆะ? นี้รู้สึกเหมือนมันจะไวต่อหนึ่งในrm -rf /ช่วงเวลาที่ยอดเยี่ยมเหล่านั้นในประวัติศาสตร์
ted-k42

2
@ ted-k42 ฉันจะทำสิ่งนี้เพื่อความปลอดภัย:when: artifact_path is defined and artifact_path != ""
bmaupin

69

ใช้โมดูลเชลล์ ( idempotentด้วย):

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

วิธีแก้ปัญหาที่สะอาดที่สุดถ้าคุณไม่สนใจวันที่สร้างและเจ้าของ / สิทธิ์:

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

7
ใช้งานได้ แต่ไม่ได้ลบไฟล์ที่ขึ้นต้นด้วย เช่น. htaccess
Abbas

เชลล์ก็ทำงานให้ฉันเช่นกัน งานเดียวกันที่แน่นอน แต่เปลี่ยนshellเป็นcommandและทำงานได้
SomethingOn

4
สัญลักษณ์แทนจะไม่ทำงานกับคำสั่งเนื่องจากต้องการเชลล์เพื่อขยาย
JamesP

1
โปรดทราบว่าการดำเนินการนี้อาจเปลี่ยนการอนุญาต / เจ้าของของคุณเว้นแต่คุณจะตั้งค่าไว้อย่างชัดเจนในช่วงเวลาที่สร้าง
NeverEndingQueue

การใช้เชลล์คุณจะได้รับคำเตือนเกี่ยวกับการใช้โมดูลไฟล์ที่มี state = absent แทน shell rm เพื่อหลีกเลี่ยงเพียงเพิ่ม args: warn: false
Rodrigo

60

ลบไดเรกทอรี (โดยทั่วไปจะเป็นสำเนาของhttps://stackoverflow.com/a/38201611/1695680 ) Ansible จะดำเนินการนี้rmtreeภายใต้ประทุน

- 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

หากคุณไม่มีความหรูหราในการลบไดเรกทอรีทั้งหมดและสร้างมันใหม่คุณสามารถสแกนหาไฟล์ (และไดเรกทอรี) และลบออกทีละรายการ ซึ่งจะใช้เวลาสักครู่ คุณอาจต้องการให้แน่ใจว่าคุณมี[ssh_connection]\npipelining = Trueใน 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
      }}

6
ภารกิจแรกคือทางออกที่ดีที่สุดที่ฉันเคยเห็น โปรดทราบความคิดเห็นที่อื่นว่ามีคำขอคุณสมบัติที่ใช้เวลานานในการเพิ่มstate=empty
William Turrell

24

ฉันไม่ชอบวิธีแก้ปัญหา rm จริงๆยังให้คำเตือนเกี่ยวกับการใช้ rm ด้วย ดังนั้นนี่คือวิธีการทำโดยไม่ต้องใช้ RM และไม่มีการเตือนที่เตือนใจได้

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

แหล่งที่มา: http://www.mydailytutorials.com/ansible-delete-multiple-files-directories-ansible/


แต่ทางออกที่ดีที่สุดสำหรับคำถามนี้ !!
Vsegar

18

ลองคำสั่งด้านล่างมันควรจะทำงาน

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

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

3
คุณพลาดที่จะหลีกเลี่ยงบรรทัดสุดท้ายด้วย {{,}} เพื่อรับwith_items: "{{ contents.stdout_lines }}"
Valerio Crini

มันอันตรายที่จะใช้ls'เอาท์พุทเพื่อรับชื่อไฟล์เพราะพิมพ์ชื่อไฟล์ไม่ถูกต้องด้วยอักขระพิเศษเช่นการขึ้นบรรทัดใหม่
bfontaine

5

สร้างการใช้งานโดยรวมที่ได้รับการประเมินใหม่และไม่ปลอดภัยจากความคิดเห็นและคำแนะนำทั้งหมด:

# 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

ฉันคิดว่าคุณกำลังขาดหายไปregisterสำหรับplugin_dir_deletedใช่มั้ย?
Bob Vork

ขอบคุณที่ชี้นำสิ่งนี้ ฉันมีรหัสชิ้นนี้นำมาจากหนึ่งใน playbooks ของฉันและทำให้เป็นชื่อสามัญมากขึ้นในแง่ของการตั้งชื่อ แต่ลืมแทนที่ชื่อตัวแปรสองตัว
Markus

1
สิ่งที่ดี แต่ฉันคิดว่ารัฐในภารกิจสุดท้ายจะต้องตั้งค่าเป็น "ไดเรกทอรี" แทนที่จะเป็น "ปัจจุบัน"
Andrew Allaire

1
คุณควรใช้ผลลัพธ์สถิติของคุณเพื่อสงวนสิทธิ์: เจ้าของจาก pw_name กลุ่มจาก gr_name และโหมดจากโหมด
DylanYoung

พยายาม owner: dir_to_delete.stat.pw_name, group: dir_to_delete.stat.gr_name mode: dir_to_delete.stat.modeแต่มันล้มเหลวกับฉันกับรุ่น
Markus

3

การใช้ไฟล์ glob ก็จะใช้งานได้ มีข้อผิดพลาดทางไวยากรณ์ในรหัสที่คุณโพสต์ ฉันได้แก้ไขและทดสอบแล้วว่าควรใช้งานได้

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

7
with_fileglobใช้งานได้เฉพาะบนเครื่องโลคัลไม่ใช่รีโมตเท่านั้น ไม่เป็นความจริงเหรอ?
Stepan Vavra

จริง .. with_fileglob สำหรับในท้องถิ่นเท่านั้น
Deepali Mittal

นอกจากนี้จะไม่ลบไดเรกทอรีเพียงไฟล์จะถูกลบ
vikas027

2

ในขณะที่ Ansible ยังคงมีการโต้วาทีในการใช้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 }}"

โปรดทราบว่าเมื่อใช้การซิงโครไนซ์คุณควรจะสามารถซิงค์ไฟล์ (พร้อมลบ) ได้อย่างถูกต้อง


2

นั่นคือสิ่งที่ฉันเกิดขึ้นกับ:

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

ก่อนอื่นเราจะได้รายชื่อไดเรกทอรีพร้อมfindตั้งค่า

  • file_typeไปanyดังนั้นเราจะไม่พลาดไดเรกทอรีที่ซ้อนกันและการเชื่อมโยง
  • hiddenเป็นyesดังนั้นเราจะไม่ข้ามไฟล์ที่ซ่อนอยู่
  • ยังไม่ได้ตั้งค่าrecurseไปyesเพราะมันไม่จำเป็นไม่เพียง แต่อาจเพิ่มระยะเวลาในการดำเนินการ

จากนั้นเราจะผ่านรายการนั้นด้วยfileโมดูล เอาท์พุทมันค่อนข้างละเอียดดังนั้นloop_control.labelจะช่วยให้เรา จำกัด ผลลัพธ์ (ดูคำแนะนำนี้ได้ที่นี่ )


แต่ฉันพบวิธีแก้ปัญหาก่อนหน้านี้ค่อนข้างช้าเนื่องจากมันวนซ้ำผ่านเนื้อหาดังนั้นฉันจึงไปกับ:

- 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 }}"
  • รับคุณสมบัติไดเรกทอรีด้วย stat
  • ลบไดเรกทอรี
  • สร้างไดเรกทอรีใหม่ด้วยคุณสมบัติเดียวกัน

นั่นก็เพียงพอแล้วสำหรับฉัน แต่คุณสามารถเพิ่มได้attributesเช่นกันหากคุณต้องการ


1

มีปัญหาเกี่ยวกับการเปิดนี้

สำหรับตอนนี้โซลูชันใช้งานได้สำหรับฉัน: สร้างโฟลเดอร์ว่างในเครื่องและซิงโครไนซ์กับรีโมต

นี่คือตัวอย่าง 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

ฉันได้เขียนโมดูล ansible ที่กำหนดเองเพื่อล้างไฟล์ตามตัวกรองหลายตัวเช่นอายุการประทับเวลารูปแบบ glob ฯลฯ

นอกจากนี้ยังเข้ากันได้กับรุ่นเก่ากว่า ansible มันสามารถพบได้ที่นี่

นี่คือตัวอย่าง:

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

0

ฉันต้องการตรวจสอบให้แน่ใจว่าคำสั่ง find ลบเฉพาะทุกอย่างในไดเรกทอรีและปล่อยให้ไดเรกทอรีไม่เปลี่ยนแปลงเพราะในกรณีของฉันไดเรกทอรีเป็นระบบไฟล์ ระบบจะสร้างข้อผิดพลาดเมื่อพยายามลบระบบไฟล์ แต่นั่นไม่ใช่ตัวเลือกที่ดี เอี่ยมใช้ตัวเลือกเชลล์เพราะนั่นเป็นเพียงตัวเลือกการทำงานที่ฉันพบจนถึงตอนนี้สำหรับคำถามนี้

ฉันทำอะไรลงไป:

แก้ไขไฟล์โฮสต์เพื่อใส่ในตัวแปรบางตัว:

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

และสร้าง playbook:

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

การดำเนินการนี้จะลบไฟล์และไดเรกทอรีทั้งหมดในไดเรกทอรี / ระบบไฟล์ตัวแปร COGNOS_HOME ตัวเลือก "-mindepth 1" ทำให้แน่ใจว่าไดเรกทอรีปัจจุบันจะไม่ถูกสัมผัส


0

เพียงแค่เทมเพลตคัดลอกและวางขนาดเล็กที่สะอาดกว่าของคำตอบ ThorSummoners หากคุณใช้ Ansible> = 2.3 (ความแตกต่างระหว่างไฟล์และ dirs ไม่จำเป็นอีกต่อไป)

- 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

สมมติว่าคุณใช้ Linux อยู่เสมอลองใช้findcmd

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

สิ่งนี้ควรล้างไฟล์ / โฟลเดอร์ / ซ่อนอยู่ใต้ /home/mydata/web


1
อาจใช้งานได้ แต่การใช้โมดูลเชลล์ควรเป็นทางเลือกสุดท้ายเสมอ
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

นี่คือตัวอย่างของฉัน

  1. ติดตั้ง repo
  2. ติดตั้งแพคเกจ rsyslog
  3. หยุด rsyslog
  4. ลบไฟล์ทั้งหมดที่อยู่ใน / var / log / rsyslog /
  5. เริ่ม 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

ทำงานด้านล่างสำหรับฉัน

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

นี่จะเป็นการยืนยันว่ามีไดเรกทอรีอยู่ มันจะสร้างมันถ้ามันไม่ได้ แต่ทำอะไรอย่างอื่นนอกจากรายงานตกลงถ้ามัน
Chris
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.