ansible - 从目录中删除非托管的文件?(ansible - delete unmanage

2019-09-02 01:03发布

我想递归通过目录复制呈现在那里为模板的所有.j2文件。 对于这个我目前使用下面几行:

- template: >
            src=/src/conf.d/{{ item }}
            dest=/dest/conf.d/{{ item|replace('.j2','') }}
  with_lines: find /src/conf.d/ -type f -printf "%P\n"

现在我正在寻找一种方法来从这个目录中删除非托管的文件。 例如,如果我删除一个文件/从模板/src/conf.d/我想Ansible从删除/dest/conf.d/为好。

是否有某种方式来做到这一点? 我试图与摆弄周围rsync --delete ,但我有一个问题与得到他们的后缀模板.j2删除。

Answer 1:

我不喜欢这样,假设定义为“managed_files”往上顶是列表的变量。

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

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


Answer 2:

我们这样做是我们的nginx的文件,因为我们希望他们在一个特殊的命令,来自模板,但除去非托管的人这工作:

  # loop through the nginx sites array and create a conf for each file in order
  # file will be name 01_file.conf, 02_file.conf etc
  - name: nginx_sites conf
    template: >
      src=templates/nginx/{{ item.1.template }}
      dest={{ nginx_conf_dir }}/{{ '%02d' % item.0 }}_{{ item.1.conf_name|default(item.1.template) }}
      owner={{ user }}
      group={{ group }}
      mode=0660
    with_indexed_items: nginx_sites
    notify:
      - restart nginx
    register: nginx_sites_confs

  # flatten and map the results into simple list
  # unchanged files have attribute dest, changed have attribute path
  - set_fact:
      nginx_confs: "{{ nginx_sites_confs.results|selectattr('dest', 'string')|map(attribute='dest')|list + nginx_sites_confs.results|selectattr('path', 'string')|map(attribute='path')|select|list }}"
    when: nginx_sites

  # get contents of conf dir
  - shell: ls -1 {{ nginx_conf_dir }}/*.conf
    register: contents
    when: nginx_sites

  # so we can delete the ones we don't manage
  - name: empty old confs
    file: path="{{ item }}" state=absent
    with_items: contents.stdout_lines
    when: nginx_sites and item not in nginx_confs

诀窍(你可以看到)的是,模板和with_items在寄存器结果不同的属性。 然后,你把他们变成你管理文件的列表,然后得到的目录清单,并在该列表不会被删除的。

可以用更少的代码来完成,如果你已经有文件的列表。 但在这种情况下,我创建一个索引列表,需要地图创建名单。



Answer 3:

我想分享我的这种情况下的经验。

Ansible从2.2有with_filetree循环提供简单的方式上传迪尔斯,链接,静态文件,甚至(!)的模板。 这让我的配置目录同步的最佳途径。

- name: etc config - Create directories
  file:
    path: "{{ nginx_conf_dir }}/{{ item.path }}"
    state: directory
    mode: 0755
  with_filetree: etc/nginx
  when: item.state == 'directory'

- name: etc config - Creating configuration files from templates
  template:
    src: "{{ item.src }}"
    dest: "{{ nginx_conf_dir }}/{{ item.path | regex_replace('\\.j2$', '') }}"
    mode: 0644
  with_filetree: etc/nginx
  when:
    - item.state == "file"
    - item.path | match('.+\.j2$') | bool

- name: etc config - Creating staic configuration files
  copy:
    src: "{{ item.src }}"
    dest: "{{ nginx_conf_dir }}/{{ item.path }}"
    mode: 0644
  with_filetree: etc/nginx
  when:
    - item.state == "file"
    - not (item.path | match('.+\.j2$') | bool)

- name: etc config - Recreate symlinks
  file:
    src: "{{ item.src }}"
    dest: "{{ nginx_conf_dir }}/{{ item.path }}"
    state: link
    force: yes
    mode: "{{ item.mode }}"
  with_filetree: etc/nginx
  when: item.state == "link"

下一步,我们可能需要从配置目录中删除未使用的文件。 这很简单。 我们收集上传的文件列表和远程服务器,然后拆掉diffrence上存在的文件。

但是,我们可能要在配置目录非托管的文件。 我用-prune的功能find ,以避免与非托管文件夹清空。

PS _(Y)_之后肯定我已经删除了一些非托管的文件

- name: etc config - Gathering managed files
  set_fact:
    __managed_file_path: "{{ nginx_conf_dir }}/{{ item.path | regex_replace('\\.j2$', '') }}"
  with_filetree: etc/nginx
  register: __managed_files

- name: etc config - Convert managed files to list
  set_fact: managed_files="{{ __managed_files.results | map(attribute='ansible_facts.__managed_file_path') | list }}"

- name: etc config - Gathering exist files (excluding .ansible_keep-content dirs)
  shell: find /etc/nginx -mindepth 1 -type d -exec test -e '{}/.ansible_keep-content' \; -prune -o -print
  register: exist_files
  changed_when: False

- name: etc config - Delete unmanaged files
  file: path="{{ item }}" state=absent
  with_items: "{{ exist_files.stdout_lines }}"
  when:
    - item not in managed_files


Answer 4:

这里的东西我想出了:

- template: src=/source/directory{{ item }}.j2 dest=/target/directory/{{ item }}
  register: template_results
  with_items:
    - a_list.txt
    - of_all.txt
    - templates.txt
- set_fact:
    managed_files: "{{ template_results.results|selectattr('invocation', 'defined')|map(attribute='invocation.module_args.dest')|list }}"

- debug:
    var: managed_files
    verbosity: 0

- find:
    paths: "/target/directory/"
    patterns: "*.txt"
  register: all_files
- set_fact:
    files_to_delete: "{{ all_files.files|map(attribute='path')|difference(managed_files) }}"

- debug:
    var: all_files
    verbosity: 0
- debug:
    var: files_to_delete
    verbosity: 0

- file: path={{ item }} state=absent
  with_items: "{{ files_to_delete }}"
  • 这将生成模板(不过这你想要的方式),并在“template_results”记录结果
  • 该结果被错位得到每个模板的“目标”的一个简单的列表。 跳过模板(因条件时,未显示)没有“调用”属性,所以他们过滤掉。
  • “发现”,然后用得到,应该是不存在的,除非专门编写的所有文件的列表。
  • 这则错位获得本文件的原始列表,然后将“应该是有”文件将被删除。
  • 那么剩下的“files_to_delete”被删除。

优点:你避免多次“跳过”条目删除过程中显示出来。

缺点:您需要连接各个template_results.results如果你想要做的发现之前做多模板任务/删除。



Answer 5:

有可能是一对夫妇的方式来处理这个问题,但它是不可能完全空的目标目录中的模板步骤之前的任务吗? 或者,也许模板文件拖放到一个临时目录,然后删除+在后续步骤中重命名?



Answer 6:

通常我不删除的文件,但我想补充-unmanaged后缀至名归。 样品ansible任务:

- name: Get sources.list.d files
  shell: grep -r --include=\*.list -L '^# Ansible' /etc/apt/sources.list.d || true
  register: grep_unmanaged
  changed_when: grep_unmanaged.stdout_lines

- name: Add '-unmanaged' suffix
  shell: rename 's/$/-unmanaged/' {{ item }}
  with_items: grep_unmanaged.stdout_lines

说明

grep命令使用:

  • -r做递归搜索
  • --include=\*.list -只递归搜索过程中采取与.LIST扩展名的文件
  • -L '^# Ansible' -这是没有以“#Ansible”行显示文件名
  • || true || true -这是用来忽略错误。 Ansible的ignore_errors也适用,但忽略错误ansible ansible-剧本来看这是不希望(至少对我来说)时将其显示在红色之前。

然后我寄存器grep命令的输出作为一个变量。 当用grep显示任何输出I设置此任务为改变(行changed_when负责此)。

在接下来的任务我重复grep的输出(通过grep的返回,即文件名),然后运行重命名命令后缀添加到每个文件。

就这样。 下一次运行该命令的首要任务应该是绿色和第二跳过。



Answer 7:

显然,这是不可能的,此刻ansible。 我曾在IRC mdehaan交谈,并把它归结为ansible不具有向无环图的资源,使得像这样的事情很难。

问mdehaan为例如权威的管理,他想出了这些东西sudoers.d目录:

14:17 < mdehaan> Robe: http://pastebin.com/yrdCZB0y
14:19 < Robe> mdehaan: HM
14:19 < Robe> mdehaan: that actually looks relatively sane
14:19 < mdehaan> thanks :)
14:19 < Robe> the problem I'm seeing is that I'd have to gather the managed files myself
14:19 < mdehaan> you would yes
14:19 < mdehaan> ALMOST
14:20 < mdehaan> you could do a fileglob and ... well, it would be a little gross
[..]
14:32 < mdehaan> eh, theoretical syntax, nm
14:33 < mdehaan> I could do it by writing a lookup plugin that filtered a list
14:34 < mdehaan> http://pastebin.com/rjF7QR24
14:34 < mdehaan> if that plugin existed, for instance, and iterated across lists in A that were also in B


文章来源: ansible - delete unmanaged files from directory?