我想递归通过目录复制和呈现在那里为模板的所有.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?