Ansible Playbook需求:启动单次执行与收尾单次执行任务实现
没问题,这完全可以实现!我来给你一步步拆解每个需求的具体实现方式:
核心需求拆解与实现
1. 任务一:Playbook启动时仅执行一次
要让某个任务在整个Playbook运行期间只执行一次,直接给任务加上run_once: yes即可。如果这个任务是在控制机(本地)执行的初始化操作,记得搭配delegate_to: localhost,避免在远程机器上跑无用的操作。
比如你需要提前在本地创建存放备份文件的目录,任务可以这么写:
- name: 任务一:初始化本地备份目录 file: path: /tmp/clients_backups state: directory run_once: yes delegate_to: localhost
2. 复制远程clients.tar.gz到本地
用Ansible的fetch模块就能轻松实现从远程拉取文件到本地。为了避免100台机器的同名文件互相覆盖,建议给每个拉取的文件加上主机名前缀:
- name: 拉取远程服务器的clients.tar.gz到本地 fetch: src: /path/on/remote/clients.tar.gz # 替换成远程机器上文件的实际路径 dest: /tmp/clients_backups/{{ inventory_hostname }}_clients.tar.gz flat: yes
flat: yes:禁用默认的按主机名创建子目录的行为,直接把文件放到指定的dest目录下{{ inventory_hostname }}:自动替换为当前远程机器的主机名,确保每个文件唯一
3. 任务三:最后一台机器处理完成后仅执行一次收尾
这里要用到Ansible的内置变量ansible_play_hosts_all,它会返回当前Play的所有主机列表。我们可以通过[-1]取列表的最后一个主机名,配合when条件判断当前处理的机器是否是最后一台,再加上run_once: yes确保只执行一次:
- name: 任务三:所有机器处理完成后执行收尾 shell: | echo "所有文件拉取完成,备份文件存放在/tmp/clients_backups/" # 这里可以添加你的收尾逻辑,比如合并文件、发送通知等 when: inventory_hostname == ansible_play_hosts_all[-1] run_once: yes delegate_to: localhost
完整Playbook示例
把上面的任务整合起来,完整的Playbook如下:
- name: 处理servers组机器的文件备份任务 hosts: servers gather_facts: false tasks: - name: 任务一:初始化本地备份目录 file: path: /tmp/clients_backups state: directory run_once: yes delegate_to: localhost tags: init - name: 拉取远程服务器的clients.tar.gz到本地 fetch: src: /path/on/remote/clients.tar.gz dest: /tmp/clients_backups/{{ inventory_hostname }}_clients.tar.gz flat: yes tags: fetch - name: 任务三:所有机器处理完成后执行收尾 shell: | echo "备份完成!共处理了{{ ansible_play_hosts_all | length }}台机器" ls -l /tmp/clients_backups/ when: inventory_hostname == ansible_play_hosts_all[-1] run_once: yes delegate_to: localhost tags: cleanup
注意事项
- 如果你用的是Ansible 2.8之前的版本,
ansible_play_hosts_all可能不支持,可以用play_hosts替代(不过这个变量在新版本已被标记为废弃) - 确保控制机的
/tmp/clients_backups目录有写入权限,任务一的初始化操作已经帮你创建了这个目录 - 如果不同远程机器上的
clients.tar.gz路径不一样,可以用变量或者条件判断来适配不同场景
内容的提问来源于stack exchange,提问作者user1950349
相关产品推荐
相关产品推荐

