如何确保Ansible shell命令在每个主机上仅执行一次?

Kei*_*ett 5 shell ansible

我希望能够保证,在给定主机上成功运行了长时间运行的shell命令后,该主机上随后运行的剧本不会执行该命令。

我很高兴得知createsAnsible shell任务的选项(请参阅http://docs.ansible.com/ansible/shell_module.html);使用此命令,我可以在shell命令成功执行之后创建文件,并且在以后的运行中不再执行该命令:

- name: Install Jupiter theme
  shell: wp theme install ~/downloads/jupiter-theme.zip --activate
         && touch ~/ansible-flags/install-jupiter-theme
  args:
    creates: ~/ansible-flags/install-jupiter-theme
Run Code Online (Sandbox Code Playgroud)

如您所见,ansible-flags我的活动用户(deploy)的主目录中有一个用于这些控制文件的目录。

但是,这是一个很大的麻烦。有一个更好的方法吗?

另外,当我需要以其他用户身份运行某个步骤时,情况变得更加复杂。在这种情况下,我无权访问deploy主目录及其子目录。我当然可以授予访问权限,但这会增加更多的复杂性。您如何建议我处理这个问题?

Kon*_*rov 5

你的剧本应该是幂等的!
因此,任何一个任务都应该可以安全地执行多次(例如echo ok),或者您应该检查是否应该执行它。
您的任务可能如下所示:

- name: Install Jupiter theme
  shell: wp theme is-installed jupiter || wp theme install ~/downloads/jupiter-theme.zip --activate
Run Code Online (Sandbox Code Playgroud)

它将检查是否安装了 jupiter 主题,并且wp theme install只有在未安装主题时才会运行。
但这changed无论如何都会标记任务的结果。
为了让它更好,你可以这样做:

- name: Install Jupiter theme
  shell: wp theme is-installed jupiter && echo ThemeAlreadyInstalled || wp theme install ~/downloads/jupiter-theme.zip --activate
  register: cmd_result
  changed_when: cmd_result.stdout != "ThemeAlreadyInstalled"
Run Code Online (Sandbox Code Playgroud)

首先,它会检查是否已经安装了 jupiter 主题。
如果是这种情况,它将输出ThemeAlreadyInstalled并退出。
否则它会调用wp theme install.
任务的结果被注册到cmd_result.
我们使用用户changed_when参数来说明如果ThemeAlreadyInstalledansible 不应该将任务视为已更改,因此它在您的剧本输出中保持绿色。

如果你之前做了一些准备任务wp theme install(例如下载主题),你可能希望将测试作为单独的任务运行以注册结果并when在后续任务中使用子句:

- name: Check Jupiter theme is installed
  shell: wp theme is-installed jupiter && echo Present || echo Absent
  register: wp_theme
  changed_when: false

- name: Download theme
  get_url: url=...
  when: wp_theme.stdout == "Absent"

- name: Install Jupiter theme
  shell: wp theme install ~/downloads/jupiter-theme.zip --activate
  when: wp_theme.stdout == "Absent"
Run Code Online (Sandbox Code Playgroud)


udo*_*dan 4

Ansible 本身是无状态的,所以无论你使用什么技术都需要自己实现。没有比告诉 Ansible 只运行一次任务更简单的方法了。

我认为你已经拥有的东西非常简单。也许使用其他路径来检查。我非常确定wp theme install实际上会将该 zip 解压缩到某个位置,然后您可以将其与该creates选项一起使用。

有其他选择,但没有什么能让事情变得更容易:

  • 使用您喜欢的任何语言创建一个脚本,用于检查主题,如果未安装,请安装它。您可以使用script 模块执行脚本,而不是 shell 任务。

  • 安装本地事实/etc/ansible/facts.d检查主题是否已安装。然后,您可以简单地将基于该事实的条件应用于任务shell

  • 设置事实缓存,然后注册 shell 任务的结果并将其存储为事实。启用事实缓存后,您可以在以后的 playbook 运行时访问存储的结果。

事情只会变得更加复杂。该选项非常适合这种情况,如果您使用命令将 zip 解压到的creates位置,它也非常干净。wp

当然,如果您需要从另一个用户帐户访问该文件,您需要授予对该文件的访问权限。将内容存储在用户主目录中,并将权限设置为只能由所有者读取,这确实不是理想的解决方案。