如何仅删除存在的 *.web 文件

问题描述 投票:0回答:3

我需要创建一个 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
ansible
3个回答
28
投票

@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'] }}"

3
投票

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
返回的内容。


2
投票

rm -rf
不关心文件是否存在。它不会抱怨。如果文件存在,它们将被删除。如果没有,那么就没有。但结果是相同的:相同的状态代码,没有输出。那么就不需要在 Ansible 级别上处理这个问题了。

© www.soinside.com 2019 - 2024. All rights reserved.