如何使用 Ansible 自动化一次性任务?

How to use Ansible to automate one-off tasks?

我正在使用 Ansible 为我们的一些构建环境自动配置 VM,例如设置 PATH 和代理环境变量,安装全局 Node.js 工具等。这很好用,并且很容易在多个主机上自动执行常见的设置任务。所有任务都在 Ansible roles 上拆分,以分离职责并提高可重用性。

现在我 运行 进入以下内容:安装了新包后,我需要更改 PATH 环境变量 - 它不再需要我之前作为一部分添加的条目Ansible 设置。

所以我自然而然地继续更新了用于为新环境设置 PATH 变量的 Ansible 任务并删除了自定义条目(我使用 lineinfile 任务创建了 PATH 条目)。

lineinfile:
    dest: ~/.profile
    regexp: "^export {{ item.regexp }}"
    line: "export {{ item.line }}"
    create: yes
  with_items:
    - { regexp: 'PATH', line: 'PATH=:~/bin:~/node_modules/.bin:$PATH' }

我从项目的上面 line 部分删除了一个条目。如您所见,lineinfile 任务仅检查条目 export PATH 是否存在于文件中,如果不存在,则使用 export PATH=:~/bin:~/node_modules/.bin:$PATH.

创建它

现在我的问题是:由于 lineinfile 任务仅验证条目是否存在,但不检查完整值,因此我需要确保所有现有环境都已更新。我该怎么做?

有没有办法使 lineinfile 语句足够智能以验证该行的内容,即确保存在我想要的确切行(同时避免重复 PATH条目)?或者这太复杂了?

我考虑(并最终做到)的另一件事是创建一个在所有环境中更新 PATH 变量的一次性剧本:

lineinfile:
    dest: ~/.profile
    backrefs: yes
    regexp: "^export PATH=(.*)/opt/foo/bar/baz/bin[\:]*(.*)"
    line: "export PATH=\1\2"

这是一种常见情况吗 - 为一次性任务创建剧本?好处是剧本在所有主机上都是 运行 并且避免了手动工作。除此之外的可重用性很小,因为我只希望这样做一次。

这是解决这个问题的正确方法,还是有更好、更聪明的方法来完成这样的任务?

我不太确定我是否完全理解你的问题,但这些都行得通......

(1) 在 .profile 中有一条专线用于添加和删除路径。因此,除了 .profile 中的所有其他 PATH 内容外,您还有一行

export PATH=~/foo/removable:$PATH  # ANSIBLE MANAGED

您使用 line_in_file 模块添加和删除。

(2) 利用/etc/profile.d目录,然后添加(通过copytemplate) and remove a file/etc/profile.d/temporary-path.shthat contains your temporaryexport` 语句。

您使用的是哪个版本的 Ansible?由于您所描述的看起来像一个错误,因为 lineinfile 模块应该检测到该行已更改并更新它。我只是复制粘贴了您的第一个任务(只是更改了文件的路径)并且一切正常。

这是第一个运行:

➜  ~  % ansible-playbook test.yml

PLAY [all] ********************************************************************

TASK: [lineinfile ] ***********************************************************
changed: [localhost] => (item={'regexp': 'PATH', 'line': 'PATH=:~/bin:~/node_modules/.bin:$PATH'})

PLAY RECAP ********************************************************************
localhost                  : ok=1    changed=1    unreachable=0    failed=0

然后我从路径中删除了 ~/bin 并再次 运行 整个事情:

➜  ~  % ansible-playbook test.yml

PLAY [all] ********************************************************************

TASK: [lineinfile ] ***********************************************************
changed: [localhost] => (item={'regexp': 'PATH', 'line': 'PATH=:~/node_modules/.bin:$PATH'})

PLAY RECAP ********************************************************************
localhost                  : ok=1    changed=1    unreachable=0    failed=0

如您所见,模块检测到我更改了变量并更新了文件。所以一切正常。