我有以下 Ansible 剧本:
- hosts: <host>
become: true
vars:
dest_dir: <dir>
roles:
- {role: '<role>', tags: '<tag>'}
所调用的<role>
由单个任务文件组成:
- name: Copy and check file.
block:
- name: Copy
ansible.builtin.copy:
src: <source file>
dest: "{{dest_dir}}"
mode: 0666
owner: root
group: root
backup: true
register: copy_result
- name: Print result
ansible.builtin.debug:
var: copy_result
- name: Validate
ansible.builtin.shell: <script> 1
when: copy_result is changed
rescue:
- name: Revert
ansible.builtin.copy:
remote_src: true
src: "{{copy_result.backup_file}}"
dest: "{{dest_dir}}"
when: copy_result.backup_file is defined
所调用的<script>
是虚拟的,只是使用与提供的参数匹配的退出代码退出:
exit $1
如果我在目标文件已经存在但内容与源文件不同的情况下运行此命令,Ansible 将正确地将源文件复制到目标,并且我期望“Validate”节导致调用“rescue”块,这应该会“回滚”文件副本。但是,“rescue”块没有被调用;相反,剧本从“Validate”节中中止,并显示以下消息:
TASK [<task> : Validate] ******************************************************
fatal: [<host>]: FAILED! => {"changed": true, "cmd": "<script> 1", "delta": "0:00:00.010525", "end": "2024-09-17 10:49:23.559180", "msg": "non-zero return code", "rc": 1, "start": "2024-09-17 10:49:23.548655", "stderr": "", "stderr_lines": [], "stdout": "", "stdout_lines": []}
然后它进入调试器。
我确实想知道‘救援’块的‘何时’参数是否有问题,但将其注释掉会导致相同的行为。
有人能找出我在这里做错了什么吗?
首先,请注意
ansible.builtin.copy
模块有一个validate
选项。使用该选项,您可以像这样重写您的剧本:您可以用更少的代码获得相同的行为。
关于您的问题,我无法重现您显示的错误。您在问题中没有提供错误信息,因此我制作了以下最小的可重现示例:
运行此程序会产生结果(我正在使用
unixy
stdout 回调来减少输出):我们可以清楚地看到“Revert”任务正在运行。但是,请注意,“Revert”任务不会执行您想要的操作。在上面的示例中,我们的目标文件是
/tmp/testfile
,这意味着备份文件的名称类似于/tmp/testfile.893626.2024-09-17@07:11:55~
。这使得“Revert”任务相当于:这是无操作;您正在将备份文件复制到其自身上。如果您想替换目标文件,则需要在参数中提供明确的文件名
dest
而不是目录;这将使剧本看起来像这样:当“验证”任务失败时,运行即可成功恢复文件。