如何使用 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
目录,然后添加(通过copy
或template) and remove a file
/etc/profile.d/temporary-path.shthat contains your temporary
export` 语句。
您使用的是哪个版本的 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
如您所见,模块检测到我更改了变量并更新了文件。所以一切正常。
我正在使用 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
目录,然后添加(通过copy
或template) and remove a file
/etc/profile.d/temporary-path.shthat contains your temporary
export` 语句。
您使用的是哪个版本的 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
如您所见,模块检测到我更改了变量并更新了文件。所以一切正常。