首页 > 解决方案 > Ansible 将 zip 列表与目录进行比较

问题描述

编辑:我通过获取 7z 内容的校验和并检查来解决了这个问题

a) 如果目录存在 b) 如果存在 - 它的内容校验和是否匹配


我有一个使用 7zip shell 命令的 ansible 剧本,但我想检查 7z 是否已经膨胀,所以我有以下内容

- name: Get zip listing
  shell: '7z l {{ sz_file }} | tail -n +21 | head -n -2 | cut -c 54-'
  register: sz_contents

- name: Compare zip listing to file contents
  stat:
    path: '{{ extract_dir }}/{{ item }}'
    register: result
  with_items: '{{ sz_contents.stdout_lines }}'

- name: Inflate 7z file if needed
  shell: 7z x {{ sz_file }}
  when: ???

我希望发生以下情况:

  1. 第一次停止比较任务 results.stat.exists == False (7z 有很多文件,之后继续比较是没有意义的)
  2. 注册文件是否需要膨胀并根据需要进行

标签: ansible

解决方案


听起来您想让提取任务以比较任务是成功还是失败为条件,并且您希望比较任务在找到不存在的文件后立即失败。

我们可以到达那里的大部分路。

通常,stat当您将模块指向不存在的路径时,它不会触发故障。例如,以下剧本:

- hosts: localhost
  gather_facts: false
  tasks:
    - stat:
        path: /does-not-exist
      register: result

    - debug:
        var: result

产量:

TASK [stat] ***********************************************************************************
ok: [localhost]

TASK [debug] **********************************************************************************
ok: [localhost] => {
    "result": {
        "changed": false,
        "failed": false,
        "stat": {
            "exists": false
        }
    }
}

Ansible 为我们提供了failed_when控制任务何时失败的指令。这意味着我们可以重写您的比较任务,使其在丢失的文件上失败,如下所示:

- name: Compare zip listing to file contents
  stat:
    path: '{{ extract_dir }}/{{ item }}'
  register: result
  failed_when: not result.stat.exists
  ignore_errors: true
  with_items: '{{ sz_contents.stdout_lines }}'

如果传递给的文件不存在, 该failed_when指令告诉 Ansible 认为任务“失败” ,并且该指令告诉 Ansible 继续执行 playbook,而不是在任务失败时中止。statignore_errors

我们可以使用一个简单的 when指令在此任务上设置提取任务条件:

- name: Inflate 7z file if needed
  shell: 7z x {{ sz_file }}
  when: result is failed

此解决方案的唯一问题是,当单个项目导致失败时,Ansible 不会退出循环,因此它将检查所有内容sz_contents.stdout_lines

更新

我在 irc 上讨论了这个问题,@bcoca 指出when 之前已经评估过了register,所以我们实际上可以通过编写这样的比较任务来获得你想要的行为:

- name: Compare zip listing to file contents
  stat:
    path: '{{ extract_dir }}/{{ item }}'
  register: result
  when: result is defined or result is success
  failed_when: not result.stat.exists
  ignore_errors: true
  with_items: '{{ sz_contents.stdout_lines }}'

when语句将导致跳过第一次失败后的所有循环迭代。


推荐阅读