我需要创建一个 Ansible 剧本来删除特定目录中的
*.web
文件(仅当文件存在时)。
操作系统:cent OS、Redhat 5x、6x。
我尝试了以下方法但没有成功:
- stat: path=/opt/app/jboss/configuration/*.web
register: web
- shell: rm -rf /opt/app/jboss/configuration/*.web
when: web.stat.exists
@bruce-p 的答案给出了 Ansible 2.0+ 的弃用警告,但新的 with_fileglob 提供了另一个选项:
- name: Delete JBoss configuration files
ansible.builtin.file:
path: "{{ item }}"
state: absent
with_fileglob: "/opt/app/jboss/configuration/*.web"
(类似的问题删除目录中包含特定名称的所有文件有类似的答案。)
编辑:如下所述,这是行不通的;这是“奇特方式”的一个例子:
- find:
paths: /opt/app/jboss/configuration
patterns: "*.web"
register: find_results
- file:
path: "{{ item['path'] }}"
state: absent
with_items: "{{ find_results['files'] }}"
stat 模块不支持通配符,因此第一个任务不会执行您期望的操作。大多数 Ansible 模块在其参数中不支持
*
、?
等通配符,除非明确记录它们支持。 原因是通配符扩展通常由您的登录 shell(bash、zsh 等)处理,因此除非应用程序明确支持它,否则它将无法识别它们。
这里有一个简单的方法来验证这一点:
tasks:
- stat: path=/etc/*.conf
register: foo
- debug: var=foo
- stat: path=/etc/resolv.conf
register: bar
- debug: var=bar
其输出为:
ok: [localhost] => {
"var": {
"foo": {
"changed": false,
"invocation": {
"module_args": "path=/etc/*.conf",
"module_complex_args": {},
"module_name": "stat"
},
"stat": {
"exists": false
}
}
}
}
TASK: [stat path=/etc/resolv.conf] ********************************************
ok: [localhost]
TASK: [debug var=bar] *********************************************************
ok: [localhost] => {
"var": {
"bar": {
"changed": false,
"invocation": {
"module_args": "path=/etc/resolv.conf",
"module_complex_args": {},
"module_name": "stat"
},
"stat": {
"atime": 1446665095.0724516,
"checksum": "fd75f8cc67e4879fa546cbbd901b211bcb7e1b5e",
"ctime": 1446840004.4182615,
"dev": 51713,
"exists": true,
"gid": 0,
"gr_name": "root",
"inode": 146096,
"isblk": false,
"ischr": false,
"isdir": false,
"isfifo": false,
"isgid": false,
"islnk": false,
"isreg": true,
"issock": false,
"isuid": false,
"md5": "a56ca5f7379429d3b358ce922b28039b",
"mode": "0644",
"mtime": 1446840004.4182615,
"nlink": 1,
"path": "/etc/resolv.conf",
"pw_name": "root",
"rgrp": true,
"roth": true,
"rusr": true,
"size": 94,
"uid": 0,
"wgrp": false,
"woth": false,
"wusr": true,
"xgrp": false,
"xoth": false,
"xusr": false
}
}
}
}
请注意,当您指定单个文件时,它会返回该文件的结果,但当您指定通配符时,它基本上不会返回任何内容。
正如@udondan 在他的回答中暗示的那样,你可以这样做:
- shell: rm -rf /opt/app/jboss/configuration/*.web
因为如果有 0 个匹配,
rm
将默默完成,不会出现错误。
如果你真的想变得更奇特,你可以使用 find 模块来查找与你的模式匹配的所有文件,然后调用
rm
命令(或者更好的是使用 file 模块并设置 state=absent
)使用一个 with_items 循环来循环 find
返回的内容。
rm -rf
不关心文件是否存在。它不会抱怨。如果文件存在,它们将被删除。如果没有,那么就没有。但结果是相同的:相同的状态代码,没有输出。那么就不需要在 Ansible 级别上处理这个问题了。