块
块创建任务的逻辑分组。块还提供处理任务错误的方法,类似于许多编程语言中的异常处理。
使用块分组任务
块中的所有任务都继承在块级别应用的指令。大多数可以在单个任务上应用的内容(循环除外)都可以在块级别应用,因此块使设置对任务通用的数据或指令变得更加容易。该指令不会影响块本身,它只会被块中包含的任务继承。例如,when 语句应用于块内的任务,而不是块本身。
tasks:
- name: Install, configure, and start Apache
when: ansible_facts['distribution'] == 'CentOS'
block:
- name: Install httpd and memcached
ansible.builtin.yum:
name:
- httpd
- memcached
state: present
- name: Apply the foo config template
ansible.builtin.template:
src: templates/src.j2
dest: /etc/foo.conf
- name: Start service bar and enable it
ansible.builtin.service:
name: bar
state: started
enabled: True
become: true
become_user: root
ignore_errors: true
在上面的示例中,‘when’ 条件将在 Ansible 运行块中的三个任务之前进行评估。所有三个任务也继承特权升级指令,以 root 用户身份运行。最后,ignore_errors: true
确保即使某些任务失败,Ansible 也会继续执行剧本。
注意
块中的所有任务,包括通过 include_role 包含的任务,都继承在块级别应用的指令。
块名称自 Ansible 2.3 开始可用。我们建议在块中或其他地方的所有任务中使用名称,以便在运行剧本时更好地了解正在执行的任务。
使用块处理错误
可以使用带有 rescue
和 always
部分的块来控制 Ansible 如何响应任务错误。
Rescue 块指定当块中较早的任务失败时要运行的任务。这种方法类似于许多编程语言中的异常处理。Ansible 仅在任务返回 ‘failed’ 状态后才运行 rescue 块。错误的任务定义和不可达的主机不会触发 rescue 块。
tasks:
- name: Handle the error
block:
- name: Print a message
ansible.builtin.debug:
msg: 'I execute normally'
- name: Force a failure
ansible.builtin.command: /bin/false
- name: Never print this
ansible.builtin.debug:
msg: 'I never execute, due to the above task failing, :-('
rescue:
- name: Print when errors
ansible.builtin.debug:
msg: 'I caught an error, can do stuff here to fix it, :-)'
您还可以向块添加 always
部分。always
部分中的任务无论前一个块的任务状态如何都会运行。
tasks:
- name: Always do X
block:
- name: Print a message
ansible.builtin.debug:
msg: 'I execute normally'
- name: Force a failure
ansible.builtin.command: /bin/false
- name: Never print this
ansible.builtin.debug:
msg: 'I never execute :-('
always:
- name: Always do this
ansible.builtin.debug:
msg: "This always executes, :-)"
这些元素共同提供复杂的错误处理。
tasks:
- name: Attempt and graceful roll back demo
block:
- name: Print a message
ansible.builtin.debug:
msg: 'I execute normally'
- name: Force a failure
ansible.builtin.command: /bin/false
- name: Never print this
ansible.builtin.debug:
msg: 'I never execute, due to the above task failing, :-('
rescue:
- name: Print when errors
ansible.builtin.debug:
msg: 'I caught an error'
- name: Force a failure in middle of recovery! >:-)
ansible.builtin.command: /bin/false
- name: Never print this
ansible.builtin.debug:
msg: 'I also never execute :-('
always:
- name: Always do this
ansible.builtin.debug:
msg: "This always executes"
block
中的任务正常执行。如果块中的任何任务返回 failed
,则 rescue
部分执行任务以从错误中恢复。always
部分无论 block
和 rescue
部分的结果如何都会运行。
如果块中发生错误并且 rescue 任务成功,Ansible 将为此次运行恢复原始任务的失败状态,并继续运行剧本,就好像原始任务已成功一样。已恢复的任务被认为是成功的,不会触发 max_fail_percentage
或 any_errors_fatal
配置。但是,Ansible 仍然在剧本统计信息中报告失败。
可以在 rescue 任务中将块与 flush_handlers
一起使用,以确保即使发生错误,所有处理程序也会运行
tasks:
- name: Attempt and graceful roll back demo
block:
- name: Print a message
ansible.builtin.debug:
msg: 'I execute normally'
changed_when: true
notify: Run me even after an error
- name: Force a failure
ansible.builtin.command: /bin/false
rescue:
- name: Make sure all handlers run
meta: flush_handlers
handlers:
- name: Run me even after an error
ansible.builtin.debug:
msg: 'This handler runs even on error'
版本 2.1 中的新功能。
Ansible 为 rescue
部分中的任务提供了几个变量
- ansible_failed_task
返回 ‘failed’ 并触发 rescue 的任务。例如,要获取名称,请使用
ansible_failed_task.name
。- ansible_failed_result
触发 rescue 的失败任务的捕获的返回值结果。这相当于在
register
关键字中使用此变量。
这些可以在 rescue
部分中进行检查
tasks:
- name: Attempt and graceful roll back demo
block:
- name: Do Something
ansible.builtin.shell: grep $(whoami) /etc/hosts
- name: Force a failure, if previous one succeeds
ansible.builtin.command: /bin/false
rescue:
- name: All is good if the first task failed
when: ansible_failed_task.name == 'Do Something'
ansible.builtin.debug:
msg: All is good, ignore error as grep could not find 'me' in hosts
- name: All is good if the second task failed
when: "'/bin/false' in ansible_failed_result.cmd | d([])"
ansible.builtin.fail:
msg: It is still false!!!
注意
在 ansible-core
2.14 或更高版本中,当嵌套块时,这两个变量都从内部块传播到块的外部 rescue
部分。
另请参阅
- Ansible 剧本
剧本简介
- 角色
按角色组织剧本
- 沟通
有问题?需要帮助?想分享你的想法?请访问 Ansible 沟通指南