Ansible:ディレクトリ内のファイルとフォルダを削除する方法は?


152

以下のコードは、webディレクトリ内にある最初のファイルのみを削除します。Webディレクトリー内のすべてのファイルとフォルダーを削除し、Webディレクトリーを保持したい。どうやってやるの?

  - 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を使用しています


バグのようです。
16年

回答:


132

以下のコードはの内容全体を削除します artifact_path

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

:これにより、ディレクトリも削除されます。


3
引用符は必要ありません。これは私の作業コードのみです。Artifact_pathは/ app / my_app / work /のようなものです
Mohan Kumar P

83
OP(および私自身)は、フォルダー自体ではなくフォルダーの内容を削除するソリューションを求めています。このソリューションは、コンテンツとフォルダー自体を削除します。
確率論的

19
これはどうして賛成票を得たのですか?これにより、ディレクトリも削除されます。
deppfx 2017年

17
上記のコードが失敗し、artifact_pathがnullになる人はいますか?それのようなこの感触は、これらの素晴らしいのいずれかに影響を受けやすい可能性がrm -rf /歴史の中で瞬間
テッド-K42

2
@ ted-k42安全のために、次のようなことをしますwhen: artifact_path is defined and artifact_path != ""
。– bmaupin

69

シェルモジュールの使用(べき等性も):

- 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 2019年

使用するシェルは、あなたの代わりにシェルのrmの状態=不在でのファイルのモジュールを使用しての警告を取得します。これを回避するには、argsを
ロドリゴ

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

ディレクトリ全体を削除して再作成する余裕がない場合は、ファイル(およびディレクトリ)をスキャンして、1つずつ削除できます。しばらくかかります。あなたはおそらくあなたが[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ソリューションが好きではありませんでした、またansibleはrmの使用について警告を出します。したがって、rmを必要とせず、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 }}"

ソース: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 }}"
なかった

ls'出力を使用してファイル名を取得することは、改行などの特殊文字を含むファイル名を正しく印刷しないため危険です。
bfontaine 2017年

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

registerfor が欠けていると思いますよねplugin_dir_deleted
Bob Vork 2018

これを指摘してくれてありがとう。私はこのコードをプレイブックの1つから取り出し、命名に関してより一般的にしましたが、2つの変数名を置き換えるのを忘れました
Markus

1
良いことですが、最後のタスクの状態は「現在」ではなく「ディレクトリ」に設定する必要があると思います。
Andrew Allaire、2018

1
stat結果を使用して、権限を保持する必要があります。所有者はpw_name、グループはgr_name、モードはmodeです。
DylanYoung 2018年

試しました owner: dir_to_delete.stat.pw_name, group: dir_to_delete.stat.gr_name mode: dir_to_delete.stat.modeが、現在のAnsibleバージョンで失敗します:(
Markus

3

ファイルglobを使用しても機能します。投稿したコードに構文エラーがあります。私はこれを修正してテストしましたが、うまくいくはずです。

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

7
with_fileglobローカルマシンでのみ機能し、リモートマシンでは機能しません。それは本当ではないですか?
Stepan Vavra

True .. with_fileglobはローカル専用です
Deepali Mittal '19

また、これはディレクトリを削除するのではなく、ファイルが削除されるだけです。
vikas027 2017

2

Ansibleはまだhttps://github.com/ansible/ansible-modules-core/issues/902の実装について議論していstate = 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 }}"

ただし、同期を使用すると、ファイルを(削除して)正しく同期できるはずです。


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、隠しファイルをスキップしません
  • また、設定しないでくださいrecurseyesそれだけではなく不要であるため、しかし、実行時間を増大させることができます。

次に、そのリストを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

これに関して未解決問題があります。

とりあえず、私にとってソリューションは機能します。空のフォルダーをローカルに作成し、それをリモートのフォルダーと同期します。

以下はサンプルプレイブックです。

- 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モジュールを作成しました。

また、古いバージョンのansibleとも互換性があります。それは見つけることができるここに

次に例を示します。

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

0

私の場合、ディレクトリはファイルシステムであるため、findコマンドはディレクトリ内のすべてを削除し、ディレクトリはそのままにしておきます。システムはファイルシステムを削除しようとするとエラーを生成しますが、それは良いオプションではありません。シェルオプションを使用しているのは、この質問でこれまでに見つけた唯一の有効なオプションだからです。

私がしたこと:

hostsファイルを編集して、いくつかの変数を入力します。

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

プレイブックを作成します。

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

これにより、COGNOS_HOME変数directory / filesystem内のすべてのファイルとディレクトリが削除されます。「-mindepth 1」オプションは、現在のディレクトリが変更されないようにします。


0

Ansible> = 2.3を使用している場合は、ThorSummonersの小さなクリーナーコピー&ペーストテンプレートが答えます(ファイルとディレクトリの区別はもう必要ありません)。

- 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. リポジトリをインストール
  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

これは、ディレクトリが存在することを確認するだけです。作成しない場合は作成しますが、作成する場合はOKを報告するだけです。
クリス・
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.